aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/raw3270.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/raw3270.c')
-rw-r--r--drivers/s390/char/raw3270.c100
1 files changed, 88 insertions, 12 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 328d9cbc56a3..d66946443dfc 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -25,6 +25,12 @@
25 25
26#include "raw3270.h" 26#include "raw3270.h"
27 27
28#include <linux/major.h>
29#include <linux/kdev_t.h>
30#include <linux/device.h>
31
32struct class *class3270;
33
28/* The main 3270 data structure. */ 34/* The main 3270 data structure. */
29struct raw3270 { 35struct raw3270 {
30 struct list_head list; 36 struct list_head list;
@@ -41,6 +47,8 @@ struct raw3270 {
41 struct timer_list timer; /* Device timer. */ 47 struct timer_list timer; /* Device timer. */
42 48
43 unsigned char *ascebc; /* ascii -> ebcdic table */ 49 unsigned char *ascebc; /* ascii -> ebcdic table */
50 struct class_device *clttydev; /* 3270-class tty device ptr */
51 struct class_device *cltubdev; /* 3270-class tub device ptr */
44}; 52};
45 53
46/* raw3270->flags */ 54/* raw3270->flags */
@@ -317,6 +325,22 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
317} 325}
318 326
319int 327int
328raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
329{
330 struct raw3270 *rp;
331 int rc;
332
333 rp = view->dev;
334 if (!rp || rp->view != view)
335 rc = -EACCES;
336 else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
337 rc = -ENODEV;
338 else
339 rc = __raw3270_start(rp, view, rq);
340 return rc;
341}
342
343int
320raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq) 344raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
321{ 345{
322 struct raw3270 *rp; 346 struct raw3270 *rp;
@@ -744,6 +768,22 @@ raw3270_reset_device(struct raw3270 *rp)
744 return rc; 768 return rc;
745} 769}
746 770
771int
772raw3270_reset(struct raw3270_view *view)
773{
774 struct raw3270 *rp;
775 int rc;
776
777 rp = view->dev;
778 if (!rp || rp->view != view)
779 rc = -EACCES;
780 else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
781 rc = -ENODEV;
782 else
783 rc = raw3270_reset_device(view->dev);
784 return rc;
785}
786
747/* 787/*
748 * Setup new 3270 device. 788 * Setup new 3270 device.
749 */ 789 */
@@ -774,11 +814,12 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
774 814
775 /* 815 /*
776 * Add device to list and find the smallest unused minor 816 * Add device to list and find the smallest unused minor
777 * number for it. 817 * number for it. Note: there is no device with minor 0,
818 * see special case for fs3270.c:fs3270_open().
778 */ 819 */
779 down(&raw3270_sem); 820 down(&raw3270_sem);
780 /* Keep the list sorted. */ 821 /* Keep the list sorted. */
781 minor = 0; 822 minor = RAW3270_FIRSTMINOR;
782 rp->minor = -1; 823 rp->minor = -1;
783 list_for_each(l, &raw3270_devices) { 824 list_for_each(l, &raw3270_devices) {
784 tmp = list_entry(l, struct raw3270, list); 825 tmp = list_entry(l, struct raw3270, list);
@@ -789,7 +830,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
789 } 830 }
790 minor++; 831 minor++;
791 } 832 }
792 if (rp->minor == -1 && minor < RAW3270_MAXDEVS) { 833 if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
793 rp->minor = minor; 834 rp->minor = minor;
794 list_add_tail(&rp->list, &raw3270_devices); 835 list_add_tail(&rp->list, &raw3270_devices);
795 } 836 }
@@ -941,11 +982,12 @@ raw3270_deactivate_view(struct raw3270_view *view)
941 list_add_tail(&view->list, &rp->view_list); 982 list_add_tail(&view->list, &rp->view_list);
942 /* Try to activate another view. */ 983 /* Try to activate another view. */
943 if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) { 984 if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
944 list_for_each_entry(view, &rp->view_list, list) 985 list_for_each_entry(view, &rp->view_list, list) {
945 if (view->fn->activate(view) == 0) { 986 rp->view = view;
946 rp->view = view; 987 if (view->fn->activate(view) == 0)
947 break; 988 break;
948 } 989 rp->view = 0;
990 }
949 } 991 }
950 } 992 }
951 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 993 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -961,6 +1003,8 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
961 struct raw3270 *rp; 1003 struct raw3270 *rp;
962 int rc; 1004 int rc;
963 1005
1006 if (minor <= 0)
1007 return -ENODEV;
964 down(&raw3270_sem); 1008 down(&raw3270_sem);
965 rc = -ENODEV; 1009 rc = -ENODEV;
966 list_for_each_entry(rp, &raw3270_devices, list) { 1010 list_for_each_entry(rp, &raw3270_devices, list) {
@@ -976,7 +1020,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
976 view->cols = rp->cols; 1020 view->cols = rp->cols;
977 view->ascebc = rp->ascebc; 1021 view->ascebc = rp->ascebc;
978 spin_lock_init(&view->lock); 1022 spin_lock_init(&view->lock);
979 list_add_tail(&view->list, &rp->view_list); 1023 list_add(&view->list, &rp->view_list);
980 rc = 0; 1024 rc = 0;
981 } 1025 }
982 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 1026 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -1039,7 +1083,7 @@ raw3270_del_view(struct raw3270_view *view)
1039 if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) { 1083 if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
1040 /* Try to activate another view. */ 1084 /* Try to activate another view. */
1041 list_for_each_entry(nv, &rp->view_list, list) { 1085 list_for_each_entry(nv, &rp->view_list, list) {
1042 if (nv->fn->activate(view) == 0) { 1086 if (nv->fn->activate(nv) == 0) {
1043 rp->view = nv; 1087 rp->view = nv;
1044 break; 1088 break;
1045 } 1089 }
@@ -1063,6 +1107,12 @@ raw3270_delete_device(struct raw3270 *rp)
1063 1107
1064 /* Remove from device chain. */ 1108 /* Remove from device chain. */
1065 down(&raw3270_sem); 1109 down(&raw3270_sem);
1110 if (rp->clttydev)
1111 class_device_destroy(class3270,
1112 MKDEV(IBM_TTY3270_MAJOR, rp->minor));
1113 if (rp->cltubdev)
1114 class_device_destroy(class3270,
1115 MKDEV(IBM_FS3270_MAJOR, rp->minor));
1066 list_del_init(&rp->list); 1116 list_del_init(&rp->list);
1067 up(&raw3270_sem); 1117 up(&raw3270_sem);
1068 1118
@@ -1129,6 +1179,16 @@ raw3270_create_attributes(struct raw3270 *rp)
1129{ 1179{
1130 //FIXME: check return code 1180 //FIXME: check return code
1131 sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); 1181 sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
1182 rp->clttydev =
1183 class_device_create(class3270,
1184 MKDEV(IBM_TTY3270_MAJOR, rp->minor),
1185 &rp->cdev->dev, "tty%s",
1186 rp->cdev->dev.bus_id);
1187 rp->cltubdev =
1188 class_device_create(class3270,
1189 MKDEV(IBM_FS3270_MAJOR, rp->minor),
1190 &rp->cdev->dev, "tub%s",
1191 rp->cdev->dev.bus_id);
1132} 1192}
1133 1193
1134/* 1194/*
@@ -1189,13 +1249,13 @@ raw3270_set_online (struct ccw_device *cdev)
1189 return PTR_ERR(rp); 1249 return PTR_ERR(rp);
1190 rc = raw3270_reset_device(rp); 1250 rc = raw3270_reset_device(rp);
1191 if (rc) 1251 if (rc)
1192 return rc; 1252 goto failure;
1193 rc = raw3270_size_device(rp); 1253 rc = raw3270_size_device(rp);
1194 if (rc) 1254 if (rc)
1195 return rc; 1255 goto failure;
1196 rc = raw3270_reset_device(rp); 1256 rc = raw3270_reset_device(rp);
1197 if (rc) 1257 if (rc)
1198 return rc; 1258 goto failure;
1199 raw3270_create_attributes(rp); 1259 raw3270_create_attributes(rp);
1200 set_bit(RAW3270_FLAGS_READY, &rp->flags); 1260 set_bit(RAW3270_FLAGS_READY, &rp->flags);
1201 down(&raw3270_sem); 1261 down(&raw3270_sem);
@@ -1203,6 +1263,10 @@ raw3270_set_online (struct ccw_device *cdev)
1203 np->notifier(rp->minor, 1); 1263 np->notifier(rp->minor, 1);
1204 up(&raw3270_sem); 1264 up(&raw3270_sem);
1205 return 0; 1265 return 0;
1266
1267failure:
1268 raw3270_delete_device(rp);
1269 return rc;
1206} 1270}
1207 1271
1208/* 1272/*
@@ -1217,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev)
1217 struct raw3270_notifier *np; 1281 struct raw3270_notifier *np;
1218 1282
1219 rp = cdev->dev.driver_data; 1283 rp = cdev->dev.driver_data;
1284 /*
1285 * _remove is the opposite of _probe; it's probe that
1286 * should set up rp. raw3270_remove gets entered for
1287 * devices even if they haven't been varied online.
1288 * Thus, rp may validly be NULL here.
1289 */
1290 if (rp == NULL)
1291 return;
1220 clear_bit(RAW3270_FLAGS_READY, &rp->flags); 1292 clear_bit(RAW3270_FLAGS_READY, &rp->flags);
1221 1293
1222 sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group); 1294 sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
@@ -1301,6 +1373,7 @@ raw3270_init(void)
1301 if (rc == 0) { 1373 if (rc == 0) {
1302 /* Create attributes for early (= console) device. */ 1374 /* Create attributes for early (= console) device. */
1303 down(&raw3270_sem); 1375 down(&raw3270_sem);
1376 class3270 = class_create(THIS_MODULE, "3270");
1304 list_for_each_entry(rp, &raw3270_devices, list) { 1377 list_for_each_entry(rp, &raw3270_devices, list) {
1305 get_device(&rp->cdev->dev); 1378 get_device(&rp->cdev->dev);
1306 raw3270_create_attributes(rp); 1379 raw3270_create_attributes(rp);
@@ -1314,6 +1387,7 @@ static void
1314raw3270_exit(void) 1387raw3270_exit(void)
1315{ 1388{
1316 ccw_driver_unregister(&raw3270_ccw_driver); 1389 ccw_driver_unregister(&raw3270_ccw_driver);
1390 class_destroy(class3270);
1317} 1391}
1318 1392
1319MODULE_LICENSE("GPL"); 1393MODULE_LICENSE("GPL");
@@ -1335,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view);
1335EXPORT_SYMBOL(raw3270_activate_view); 1409EXPORT_SYMBOL(raw3270_activate_view);
1336EXPORT_SYMBOL(raw3270_deactivate_view); 1410EXPORT_SYMBOL(raw3270_deactivate_view);
1337EXPORT_SYMBOL(raw3270_start); 1411EXPORT_SYMBOL(raw3270_start);
1412EXPORT_SYMBOL(raw3270_start_locked);
1338EXPORT_SYMBOL(raw3270_start_irq); 1413EXPORT_SYMBOL(raw3270_start_irq);
1414EXPORT_SYMBOL(raw3270_reset);
1339EXPORT_SYMBOL(raw3270_register_notifier); 1415EXPORT_SYMBOL(raw3270_register_notifier);
1340EXPORT_SYMBOL(raw3270_unregister_notifier); 1416EXPORT_SYMBOL(raw3270_unregister_notifier);
1341EXPORT_SYMBOL(raw3270_wait_queue); 1417EXPORT_SYMBOL(raw3270_wait_queue);