0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/err.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/list.h>
0016 #include <linux/slab.h>
0017 #include <linux/types.h>
0018 #include <linux/wait.h>
0019
0020 #include <asm/ccwdev.h>
0021 #include <asm/cio.h>
0022 #include <asm/ebcdic.h>
0023 #include <asm/diag.h>
0024
0025 #include "raw3270.h"
0026
0027 #include <linux/major.h>
0028 #include <linux/kdev_t.h>
0029 #include <linux/device.h>
0030 #include <linux/mutex.h>
0031
0032 struct class *class3270;
0033
0034
0035 struct raw3270 {
0036 struct list_head list;
0037 struct ccw_device *cdev;
0038 int minor;
0039
0040 short model, rows, cols;
0041 unsigned int state;
0042 unsigned long flags;
0043
0044 struct list_head req_queue;
0045 struct list_head view_list;
0046 struct raw3270_view *view;
0047
0048 struct timer_list timer;
0049
0050 unsigned char *ascebc;
0051
0052 struct raw3270_view init_view;
0053 struct raw3270_request init_reset;
0054 struct raw3270_request init_readpart;
0055 struct raw3270_request init_readmod;
0056 unsigned char init_data[256];
0057 };
0058
0059
0060 #define RAW3270_STATE_INIT 0
0061 #define RAW3270_STATE_RESET 1
0062 #define RAW3270_STATE_W4ATTN 2
0063 #define RAW3270_STATE_READMOD 3
0064 #define RAW3270_STATE_READY 4
0065
0066
0067 #define RAW3270_FLAGS_14BITADDR 0
0068 #define RAW3270_FLAGS_BUSY 1
0069 #define RAW3270_FLAGS_CONSOLE 2
0070
0071
0072 static DEFINE_MUTEX(raw3270_mutex);
0073
0074
0075 static LIST_HEAD(raw3270_devices);
0076
0077
0078
0079
0080
0081
0082 static int raw3270_registered;
0083
0084
0085 static bool tubxcorrect;
0086 module_param(tubxcorrect, bool, 0);
0087
0088
0089
0090
0091 DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue);
0092
0093 static void __raw3270_disconnect(struct raw3270 *rp);
0094
0095
0096
0097
0098 static unsigned char raw3270_ebcgraf[64] = {
0099 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0100 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0101 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0102 0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0103 0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0104 0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0105 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0106 0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
0107 };
0108
0109 static inline int raw3270_state_ready(struct raw3270 *rp)
0110 {
0111 return rp->state == RAW3270_STATE_READY;
0112 }
0113
0114 static inline int raw3270_state_final(struct raw3270 *rp)
0115 {
0116 return rp->state == RAW3270_STATE_INIT ||
0117 rp->state == RAW3270_STATE_READY;
0118 }
0119
0120 void
0121 raw3270_buffer_address(struct raw3270 *rp, char *cp, unsigned short addr)
0122 {
0123 if (test_bit(RAW3270_FLAGS_14BITADDR, &rp->flags)) {
0124 cp[0] = (addr >> 8) & 0x3f;
0125 cp[1] = addr & 0xff;
0126 } else {
0127 cp[0] = raw3270_ebcgraf[(addr >> 6) & 0x3f];
0128 cp[1] = raw3270_ebcgraf[addr & 0x3f];
0129 }
0130 }
0131
0132
0133
0134
0135 struct raw3270_request *
0136 raw3270_request_alloc(size_t size)
0137 {
0138 struct raw3270_request *rq;
0139
0140
0141 rq = kzalloc(sizeof(struct raw3270_request), GFP_KERNEL | GFP_DMA);
0142 if (!rq)
0143 return ERR_PTR(-ENOMEM);
0144
0145
0146 if (size > 0) {
0147 rq->buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
0148 if (!rq->buffer) {
0149 kfree(rq);
0150 return ERR_PTR(-ENOMEM);
0151 }
0152 }
0153 rq->size = size;
0154 INIT_LIST_HEAD(&rq->list);
0155
0156
0157
0158
0159 rq->ccw.cda = __pa(rq->buffer);
0160 rq->ccw.flags = CCW_FLAG_SLI;
0161
0162 return rq;
0163 }
0164
0165
0166
0167
0168 void
0169 raw3270_request_free (struct raw3270_request *rq)
0170 {
0171 kfree(rq->buffer);
0172 kfree(rq);
0173 }
0174
0175
0176
0177
0178 void
0179 raw3270_request_reset(struct raw3270_request *rq)
0180 {
0181 BUG_ON(!list_empty(&rq->list));
0182 rq->ccw.cmd_code = 0;
0183 rq->ccw.count = 0;
0184 rq->ccw.cda = __pa(rq->buffer);
0185 rq->ccw.flags = CCW_FLAG_SLI;
0186 rq->rescnt = 0;
0187 rq->rc = 0;
0188 }
0189
0190
0191
0192
0193 void
0194 raw3270_request_set_cmd(struct raw3270_request *rq, u8 cmd)
0195 {
0196 rq->ccw.cmd_code = cmd;
0197 }
0198
0199
0200
0201
0202 int
0203 raw3270_request_add_data(struct raw3270_request *rq, void *data, size_t size)
0204 {
0205 if (size + rq->ccw.count > rq->size)
0206 return -E2BIG;
0207 memcpy(rq->buffer + rq->ccw.count, data, size);
0208 rq->ccw.count += size;
0209 return 0;
0210 }
0211
0212
0213
0214
0215 void
0216 raw3270_request_set_data(struct raw3270_request *rq, void *data, size_t size)
0217 {
0218 rq->ccw.cda = __pa(data);
0219 rq->ccw.count = size;
0220 }
0221
0222
0223
0224
0225 void
0226 raw3270_request_set_idal(struct raw3270_request *rq, struct idal_buffer *ib)
0227 {
0228 rq->ccw.cda = __pa(ib->data);
0229 rq->ccw.count = ib->size;
0230 rq->ccw.flags |= CCW_FLAG_IDA;
0231 }
0232
0233
0234
0235
0236
0237 static int
0238 __raw3270_start(struct raw3270 *rp, struct raw3270_view *view,
0239 struct raw3270_request *rq)
0240 {
0241 rq->view = view;
0242 raw3270_get_view(view);
0243 if (list_empty(&rp->req_queue) &&
0244 !test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
0245
0246 rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
0247 (unsigned long) rq, 0, 0);
0248 if (rq->rc) {
0249 raw3270_put_view(view);
0250 return rq->rc;
0251 }
0252 }
0253 list_add_tail(&rq->list, &rp->req_queue);
0254 return 0;
0255 }
0256
0257 int
0258 raw3270_view_active(struct raw3270_view *view)
0259 {
0260 struct raw3270 *rp = view->dev;
0261
0262 return rp && rp->view == view;
0263 }
0264
0265 int
0266 raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
0267 {
0268 unsigned long flags;
0269 struct raw3270 *rp;
0270 int rc;
0271
0272 spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
0273 rp = view->dev;
0274 if (!rp || rp->view != view)
0275 rc = -EACCES;
0276 else if (!raw3270_state_ready(rp))
0277 rc = -EBUSY;
0278 else
0279 rc = __raw3270_start(rp, view, rq);
0280 spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
0281 return rc;
0282 }
0283
0284 int
0285 raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
0286 {
0287 struct raw3270 *rp;
0288 int rc;
0289
0290 rp = view->dev;
0291 if (!rp || rp->view != view)
0292 rc = -EACCES;
0293 else if (!raw3270_state_ready(rp))
0294 rc = -EBUSY;
0295 else
0296 rc = __raw3270_start(rp, view, rq);
0297 return rc;
0298 }
0299
0300 int
0301 raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
0302 {
0303 struct raw3270 *rp;
0304
0305 rp = view->dev;
0306 rq->view = view;
0307 raw3270_get_view(view);
0308 list_add_tail(&rq->list, &rp->req_queue);
0309 return 0;
0310 }
0311
0312
0313
0314
0315 static void
0316 raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
0317 {
0318 struct raw3270 *rp;
0319 struct raw3270_view *view;
0320 struct raw3270_request *rq;
0321
0322 rp = dev_get_drvdata(&cdev->dev);
0323 if (!rp)
0324 return;
0325 rq = (struct raw3270_request *) intparm;
0326 view = rq ? rq->view : rp->view;
0327
0328 if (!IS_ERR(irb)) {
0329
0330 if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END)
0331 clear_bit(RAW3270_FLAGS_BUSY, &rp->flags);
0332 if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END |
0333 DEV_STAT_DEV_END |
0334 DEV_STAT_UNIT_EXCEP))
0335 set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
0336
0337 if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
0338 (irb->ecw[0] & SNS0_INTERVENTION_REQ)) {
0339 set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
0340 if (rp->state > RAW3270_STATE_RESET)
0341 __raw3270_disconnect(rp);
0342 }
0343
0344 if (view)
0345 view->fn->intv(view, rq, irb);
0346 }
0347
0348 if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags))
0349
0350 return;
0351
0352 if (rq && !list_empty(&rq->list)) {
0353
0354 list_del_init(&rq->list);
0355 if (rq->callback)
0356 rq->callback(rq, rq->callback_data);
0357
0358 raw3270_put_view(view);
0359 }
0360
0361
0362
0363
0364
0365 while (!list_empty(&rp->req_queue)) {
0366 rq = list_entry(rp->req_queue.next,struct raw3270_request,list);
0367 rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
0368 (unsigned long) rq, 0, 0);
0369 if (rq->rc == 0)
0370 break;
0371
0372 list_del_init(&rq->list);
0373 if (rq->callback)
0374 rq->callback(rq, rq->callback_data);
0375
0376 raw3270_put_view(view);
0377 }
0378 }
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 struct raw3270_ua {
0390 struct {
0391 short l;
0392 char sfid;
0393 char qcode;
0394 char flags0;
0395 char flags1;
0396 short w;
0397 short h;
0398 char units;
0399 int xr;
0400 int yr;
0401 char aw;
0402 char ah;
0403 short buffsz;
0404 char xmin;
0405 char ymin;
0406 char xmax;
0407 char ymax;
0408 } __attribute__ ((packed)) uab;
0409 struct {
0410 char l;
0411 char sdpid;
0412 char res;
0413 char auaid;
0414 short wauai;
0415 short hauai;
0416 char auaunits;
0417 int auaxr;
0418 int auayr;
0419 char awauai;
0420 char ahauai;
0421 } __attribute__ ((packed)) aua;
0422 } __attribute__ ((packed));
0423
0424 static void
0425 raw3270_size_device_vm(struct raw3270 *rp)
0426 {
0427 int rc, model;
0428 struct ccw_dev_id dev_id;
0429 struct diag210 diag_data;
0430
0431 ccw_device_get_id(rp->cdev, &dev_id);
0432 diag_data.vrdcdvno = dev_id.devno;
0433 diag_data.vrdclen = sizeof(struct diag210);
0434 rc = diag210(&diag_data);
0435 model = diag_data.vrdccrmd;
0436
0437 if (rc || model < 2 || model > 5)
0438 model = 2;
0439 switch (model) {
0440 case 2:
0441 rp->model = model;
0442 rp->rows = 24;
0443 rp->cols = 80;
0444 break;
0445 case 3:
0446 rp->model = model;
0447 rp->rows = 32;
0448 rp->cols = 80;
0449 break;
0450 case 4:
0451 rp->model = model;
0452 rp->rows = 43;
0453 rp->cols = 80;
0454 break;
0455 case 5:
0456 rp->model = model;
0457 rp->rows = 27;
0458 rp->cols = 132;
0459 break;
0460 }
0461 }
0462
0463 static void
0464 raw3270_size_device(struct raw3270 *rp)
0465 {
0466 struct raw3270_ua *uap;
0467
0468
0469 uap = (struct raw3270_ua *) (rp->init_data + 1);
0470
0471 if (rp->init_readmod.rc || rp->init_data[0] != 0x88 ||
0472 uap->uab.qcode != 0x81) {
0473
0474 rp->model = 2;
0475 rp->rows = 24;
0476 rp->cols = 80;
0477 return;
0478 }
0479
0480 rp->rows = uap->uab.h;
0481 rp->cols = uap->uab.w;
0482
0483 if ((uap->uab.flags0 & 0x0d) == 0x01)
0484 set_bit(RAW3270_FLAGS_14BITADDR, &rp->flags);
0485
0486 if (uap->uab.l == sizeof(struct raw3270_ua) &&
0487 uap->aua.sdpid == 0x02) {
0488 rp->rows = uap->aua.hauai;
0489 rp->cols = uap->aua.wauai;
0490 }
0491
0492 rp->model = 0;
0493 if (rp->rows == 24 && rp->cols == 80)
0494 rp->model = 2;
0495 if (rp->rows == 32 && rp->cols == 80)
0496 rp->model = 3;
0497 if (rp->rows == 43 && rp->cols == 80)
0498 rp->model = 4;
0499 if (rp->rows == 27 && rp->cols == 132)
0500 rp->model = 5;
0501 }
0502
0503 static void
0504 raw3270_size_device_done(struct raw3270 *rp)
0505 {
0506 struct raw3270_view *view;
0507
0508 rp->view = NULL;
0509 rp->state = RAW3270_STATE_READY;
0510
0511 list_for_each_entry(view, &rp->view_list, list)
0512 if (view->fn->resize)
0513 view->fn->resize(view, rp->model, rp->rows, rp->cols);
0514
0515 list_for_each_entry(view, &rp->view_list, list) {
0516 rp->view = view;
0517 if (view->fn->activate(view) == 0)
0518 break;
0519 rp->view = NULL;
0520 }
0521 }
0522
0523 static void
0524 raw3270_read_modified_cb(struct raw3270_request *rq, void *data)
0525 {
0526 struct raw3270 *rp = rq->view->dev;
0527
0528 raw3270_size_device(rp);
0529 raw3270_size_device_done(rp);
0530 }
0531
0532 static void
0533 raw3270_read_modified(struct raw3270 *rp)
0534 {
0535 if (rp->state != RAW3270_STATE_W4ATTN)
0536 return;
0537
0538 memset(&rp->init_readmod, 0, sizeof(rp->init_readmod));
0539 memset(&rp->init_data, 0, sizeof(rp->init_data));
0540 rp->init_readmod.ccw.cmd_code = TC_READMOD;
0541 rp->init_readmod.ccw.flags = CCW_FLAG_SLI;
0542 rp->init_readmod.ccw.count = sizeof(rp->init_data);
0543 rp->init_readmod.ccw.cda = (__u32) __pa(rp->init_data);
0544 rp->init_readmod.callback = raw3270_read_modified_cb;
0545 rp->state = RAW3270_STATE_READMOD;
0546 raw3270_start_irq(&rp->init_view, &rp->init_readmod);
0547 }
0548
0549 static void
0550 raw3270_writesf_readpart(struct raw3270 *rp)
0551 {
0552 static const unsigned char wbuf[] =
0553 { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };
0554
0555
0556 memset(&rp->init_readpart, 0, sizeof(rp->init_readpart));
0557 memset(&rp->init_data, 0, sizeof(rp->init_data));
0558 memcpy(&rp->init_data, wbuf, sizeof(wbuf));
0559 rp->init_readpart.ccw.cmd_code = TC_WRITESF;
0560 rp->init_readpart.ccw.flags = CCW_FLAG_SLI;
0561 rp->init_readpart.ccw.count = sizeof(wbuf);
0562 rp->init_readpart.ccw.cda = (__u32) __pa(&rp->init_data);
0563 rp->state = RAW3270_STATE_W4ATTN;
0564 raw3270_start_irq(&rp->init_view, &rp->init_readpart);
0565 }
0566
0567
0568
0569
0570 static void
0571 raw3270_reset_device_cb(struct raw3270_request *rq, void *data)
0572 {
0573 struct raw3270 *rp = rq->view->dev;
0574
0575 if (rp->state != RAW3270_STATE_RESET)
0576 return;
0577 if (rq->rc) {
0578
0579 rp->state = RAW3270_STATE_INIT;
0580 } else if (MACHINE_IS_VM) {
0581 raw3270_size_device_vm(rp);
0582 raw3270_size_device_done(rp);
0583 } else
0584 raw3270_writesf_readpart(rp);
0585 memset(&rp->init_reset, 0, sizeof(rp->init_reset));
0586 }
0587
0588 static int
0589 __raw3270_reset_device(struct raw3270 *rp)
0590 {
0591 int rc;
0592
0593
0594 if (rp->init_reset.view)
0595 return -EBUSY;
0596
0597 rp->init_data[0] = TW_KR;
0598 rp->init_reset.ccw.cmd_code = TC_EWRITEA;
0599 rp->init_reset.ccw.flags = CCW_FLAG_SLI;
0600 rp->init_reset.ccw.count = 1;
0601 rp->init_reset.ccw.cda = (__u32) __pa(rp->init_data);
0602 rp->init_reset.callback = raw3270_reset_device_cb;
0603 rc = __raw3270_start(rp, &rp->init_view, &rp->init_reset);
0604 if (rc == 0 && rp->state == RAW3270_STATE_INIT)
0605 rp->state = RAW3270_STATE_RESET;
0606 return rc;
0607 }
0608
0609 static int
0610 raw3270_reset_device(struct raw3270 *rp)
0611 {
0612 unsigned long flags;
0613 int rc;
0614
0615 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0616 rc = __raw3270_reset_device(rp);
0617 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0618 return rc;
0619 }
0620
0621 int
0622 raw3270_reset(struct raw3270_view *view)
0623 {
0624 struct raw3270 *rp;
0625 int rc;
0626
0627 rp = view->dev;
0628 if (!rp || rp->view != view)
0629 rc = -EACCES;
0630 else if (!raw3270_state_ready(rp))
0631 rc = -EBUSY;
0632 else
0633 rc = raw3270_reset_device(view->dev);
0634 return rc;
0635 }
0636
0637 static void
0638 __raw3270_disconnect(struct raw3270 *rp)
0639 {
0640 struct raw3270_request *rq;
0641 struct raw3270_view *view;
0642
0643 rp->state = RAW3270_STATE_INIT;
0644 rp->view = &rp->init_view;
0645
0646 while (!list_empty(&rp->req_queue)) {
0647 rq = list_entry(rp->req_queue.next,struct raw3270_request,list);
0648 view = rq->view;
0649 rq->rc = -EACCES;
0650 list_del_init(&rq->list);
0651 if (rq->callback)
0652 rq->callback(rq, rq->callback_data);
0653 raw3270_put_view(view);
0654 }
0655
0656 __raw3270_reset_device(rp);
0657 }
0658
0659 static void
0660 raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
0661 struct irb *irb)
0662 {
0663 struct raw3270 *rp;
0664
0665 if (rq) {
0666 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
0667 if (irb->ecw[0] & SNS0_CMD_REJECT)
0668 rq->rc = -EOPNOTSUPP;
0669 else
0670 rq->rc = -EIO;
0671 }
0672 }
0673 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
0674
0675 rp = view->dev;
0676 raw3270_read_modified(rp);
0677 }
0678 }
0679
0680 static struct raw3270_fn raw3270_init_fn = {
0681 .intv = raw3270_init_irq
0682 };
0683
0684
0685
0686
0687 static int
0688 raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
0689 {
0690 struct list_head *l;
0691 struct raw3270 *tmp;
0692 int minor;
0693
0694 memset(rp, 0, sizeof(struct raw3270));
0695
0696 memcpy(ascebc, _ascebc, 256);
0697 if (tubxcorrect) {
0698
0699 ascebc['['] = 0xad;
0700 ascebc[']'] = 0xbd;
0701 ascebc['^'] = 0xb0;
0702 }
0703 rp->ascebc = ascebc;
0704
0705
0706 rp->rows = 24;
0707 rp->cols = 80;
0708
0709 INIT_LIST_HEAD(&rp->req_queue);
0710 INIT_LIST_HEAD(&rp->view_list);
0711
0712 rp->init_view.dev = rp;
0713 rp->init_view.fn = &raw3270_init_fn;
0714 rp->view = &rp->init_view;
0715
0716
0717
0718
0719
0720
0721 mutex_lock(&raw3270_mutex);
0722
0723 minor = RAW3270_FIRSTMINOR;
0724 rp->minor = -1;
0725 list_for_each(l, &raw3270_devices) {
0726 tmp = list_entry(l, struct raw3270, list);
0727 if (tmp->minor > minor) {
0728 rp->minor = minor;
0729 __list_add(&rp->list, l->prev, l);
0730 break;
0731 }
0732 minor++;
0733 }
0734 if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
0735 rp->minor = minor;
0736 list_add_tail(&rp->list, &raw3270_devices);
0737 }
0738 mutex_unlock(&raw3270_mutex);
0739
0740 if (rp->minor == -1)
0741 return -EUSERS;
0742 rp->cdev = cdev;
0743 dev_set_drvdata(&cdev->dev, rp);
0744 cdev->handler = raw3270_irq;
0745 return 0;
0746 }
0747
0748 #ifdef CONFIG_TN3270_CONSOLE
0749
0750 static struct ccw_driver raw3270_ccw_driver;
0751
0752
0753
0754
0755 struct raw3270 __init *raw3270_setup_console(void)
0756 {
0757 struct ccw_device *cdev;
0758 unsigned long flags;
0759 struct raw3270 *rp;
0760 char *ascebc;
0761 int rc;
0762
0763 cdev = ccw_device_create_console(&raw3270_ccw_driver);
0764 if (IS_ERR(cdev))
0765 return ERR_CAST(cdev);
0766
0767 rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
0768 ascebc = kzalloc(256, GFP_KERNEL);
0769 rc = raw3270_setup_device(cdev, rp, ascebc);
0770 if (rc)
0771 return ERR_PTR(rc);
0772 set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
0773
0774 rc = ccw_device_enable_console(cdev);
0775 if (rc) {
0776 ccw_device_destroy_console(cdev);
0777 return ERR_PTR(rc);
0778 }
0779
0780 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0781 do {
0782 __raw3270_reset_device(rp);
0783 while (!raw3270_state_final(rp)) {
0784 ccw_device_wait_idle(rp->cdev);
0785 barrier();
0786 }
0787 } while (rp->state != RAW3270_STATE_READY);
0788 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0789 return rp;
0790 }
0791
0792 void
0793 raw3270_wait_cons_dev(struct raw3270 *rp)
0794 {
0795 unsigned long flags;
0796
0797 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0798 ccw_device_wait_idle(rp->cdev);
0799 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0800 }
0801
0802 #endif
0803
0804
0805
0806
0807 static struct raw3270 *
0808 raw3270_create_device(struct ccw_device *cdev)
0809 {
0810 struct raw3270 *rp;
0811 char *ascebc;
0812 int rc;
0813
0814 rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
0815 if (!rp)
0816 return ERR_PTR(-ENOMEM);
0817 ascebc = kmalloc(256, GFP_KERNEL);
0818 if (!ascebc) {
0819 kfree(rp);
0820 return ERR_PTR(-ENOMEM);
0821 }
0822 rc = raw3270_setup_device(cdev, rp, ascebc);
0823 if (rc) {
0824 kfree(rp->ascebc);
0825 kfree(rp);
0826 rp = ERR_PTR(rc);
0827 }
0828
0829 get_device(&cdev->dev);
0830 return rp;
0831 }
0832
0833
0834
0835
0836
0837 int raw3270_view_lock_unavailable(struct raw3270_view *view)
0838 {
0839 struct raw3270 *rp = view->dev;
0840
0841 if (!rp)
0842 return -ENODEV;
0843 if (spin_is_locked(get_ccwdev_lock(rp->cdev)))
0844 return -EBUSY;
0845 return 0;
0846 }
0847
0848
0849
0850
0851 int
0852 raw3270_activate_view(struct raw3270_view *view)
0853 {
0854 struct raw3270 *rp;
0855 struct raw3270_view *oldview, *nv;
0856 unsigned long flags;
0857 int rc;
0858
0859 rp = view->dev;
0860 if (!rp)
0861 return -ENODEV;
0862 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0863 if (rp->view == view)
0864 rc = 0;
0865 else if (!raw3270_state_ready(rp))
0866 rc = -EBUSY;
0867 else {
0868 oldview = NULL;
0869 if (rp->view && rp->view->fn->deactivate) {
0870 oldview = rp->view;
0871 oldview->fn->deactivate(oldview);
0872 }
0873 rp->view = view;
0874 rc = view->fn->activate(view);
0875 if (rc) {
0876
0877 rp->view = oldview;
0878 if (!oldview || oldview->fn->activate(oldview) != 0) {
0879
0880 list_for_each_entry(nv, &rp->view_list, list)
0881 if (nv != view && nv != oldview) {
0882 rp->view = nv;
0883 if (nv->fn->activate(nv) == 0)
0884 break;
0885 rp->view = NULL;
0886 }
0887 }
0888 }
0889 }
0890 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0891 return rc;
0892 }
0893
0894
0895
0896
0897 void
0898 raw3270_deactivate_view(struct raw3270_view *view)
0899 {
0900 unsigned long flags;
0901 struct raw3270 *rp;
0902
0903 rp = view->dev;
0904 if (!rp)
0905 return;
0906 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0907 if (rp->view == view) {
0908 view->fn->deactivate(view);
0909 rp->view = NULL;
0910
0911 list_del_init(&view->list);
0912 list_add_tail(&view->list, &rp->view_list);
0913
0914 if (raw3270_state_ready(rp)) {
0915 list_for_each_entry(view, &rp->view_list, list) {
0916 rp->view = view;
0917 if (view->fn->activate(view) == 0)
0918 break;
0919 rp->view = NULL;
0920 }
0921 }
0922 }
0923 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0924 }
0925
0926
0927
0928
0929 int
0930 raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor, int subclass)
0931 {
0932 unsigned long flags;
0933 struct raw3270 *rp;
0934 int rc;
0935
0936 if (minor <= 0)
0937 return -ENODEV;
0938 mutex_lock(&raw3270_mutex);
0939 rc = -ENODEV;
0940 list_for_each_entry(rp, &raw3270_devices, list) {
0941 if (rp->minor != minor)
0942 continue;
0943 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0944 atomic_set(&view->ref_count, 2);
0945 view->dev = rp;
0946 view->fn = fn;
0947 view->model = rp->model;
0948 view->rows = rp->rows;
0949 view->cols = rp->cols;
0950 view->ascebc = rp->ascebc;
0951 spin_lock_init(&view->lock);
0952 lockdep_set_subclass(&view->lock, subclass);
0953 list_add(&view->list, &rp->view_list);
0954 rc = 0;
0955 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0956 break;
0957 }
0958 mutex_unlock(&raw3270_mutex);
0959 return rc;
0960 }
0961
0962
0963
0964
0965 struct raw3270_view *
0966 raw3270_find_view(struct raw3270_fn *fn, int minor)
0967 {
0968 struct raw3270 *rp;
0969 struct raw3270_view *view, *tmp;
0970 unsigned long flags;
0971
0972 mutex_lock(&raw3270_mutex);
0973 view = ERR_PTR(-ENODEV);
0974 list_for_each_entry(rp, &raw3270_devices, list) {
0975 if (rp->minor != minor)
0976 continue;
0977 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
0978 list_for_each_entry(tmp, &rp->view_list, list) {
0979 if (tmp->fn == fn) {
0980 raw3270_get_view(tmp);
0981 view = tmp;
0982 break;
0983 }
0984 }
0985 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
0986 break;
0987 }
0988 mutex_unlock(&raw3270_mutex);
0989 return view;
0990 }
0991
0992
0993
0994
0995 void
0996 raw3270_del_view(struct raw3270_view *view)
0997 {
0998 unsigned long flags;
0999 struct raw3270 *rp;
1000 struct raw3270_view *nv;
1001
1002 rp = view->dev;
1003 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
1004 if (rp->view == view) {
1005 view->fn->deactivate(view);
1006 rp->view = NULL;
1007 }
1008 list_del_init(&view->list);
1009 if (!rp->view && raw3270_state_ready(rp)) {
1010
1011 list_for_each_entry(nv, &rp->view_list, list) {
1012 if (nv->fn->activate(nv) == 0) {
1013 rp->view = nv;
1014 break;
1015 }
1016 }
1017 }
1018 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
1019
1020 atomic_dec(&view->ref_count);
1021 wait_event(raw3270_wait_queue, atomic_read(&view->ref_count) == 0);
1022 if (view->fn->free)
1023 view->fn->free(view);
1024 }
1025
1026
1027
1028
1029 static void
1030 raw3270_delete_device(struct raw3270 *rp)
1031 {
1032 struct ccw_device *cdev;
1033
1034
1035 mutex_lock(&raw3270_mutex);
1036 list_del_init(&rp->list);
1037 mutex_unlock(&raw3270_mutex);
1038
1039
1040 cdev = rp->cdev;
1041 rp->cdev = NULL;
1042 dev_set_drvdata(&cdev->dev, NULL);
1043 cdev->handler = NULL;
1044
1045
1046 put_device(&cdev->dev);
1047
1048
1049 kfree(rp->ascebc);
1050 kfree(rp);
1051 }
1052
1053 static int
1054 raw3270_probe (struct ccw_device *cdev)
1055 {
1056 return 0;
1057 }
1058
1059
1060
1061
1062 static ssize_t
1063 raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
1064 {
1065 return sysfs_emit(buf, "%i\n",
1066 ((struct raw3270 *)dev_get_drvdata(dev))->model);
1067 }
1068 static DEVICE_ATTR(model, 0444, raw3270_model_show, NULL);
1069
1070 static ssize_t
1071 raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
1072 {
1073 return sysfs_emit(buf, "%i\n",
1074 ((struct raw3270 *)dev_get_drvdata(dev))->rows);
1075 }
1076 static DEVICE_ATTR(rows, 0444, raw3270_rows_show, NULL);
1077
1078 static ssize_t
1079 raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
1080 {
1081 return sysfs_emit(buf, "%i\n",
1082 ((struct raw3270 *)dev_get_drvdata(dev))->cols);
1083 }
1084 static DEVICE_ATTR(columns, 0444, raw3270_columns_show, NULL);
1085
1086 static struct attribute * raw3270_attrs[] = {
1087 &dev_attr_model.attr,
1088 &dev_attr_rows.attr,
1089 &dev_attr_columns.attr,
1090 NULL,
1091 };
1092
1093 static const struct attribute_group raw3270_attr_group = {
1094 .attrs = raw3270_attrs,
1095 };
1096
1097 static int raw3270_create_attributes(struct raw3270 *rp)
1098 {
1099 return sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
1100 }
1101
1102
1103
1104
1105 static LIST_HEAD(raw3270_notifier);
1106
1107 int raw3270_register_notifier(struct raw3270_notifier *notifier)
1108 {
1109 struct raw3270 *rp;
1110
1111 mutex_lock(&raw3270_mutex);
1112 list_add_tail(¬ifier->list, &raw3270_notifier);
1113 list_for_each_entry(rp, &raw3270_devices, list)
1114 notifier->create(rp->minor);
1115 mutex_unlock(&raw3270_mutex);
1116 return 0;
1117 }
1118
1119 void raw3270_unregister_notifier(struct raw3270_notifier *notifier)
1120 {
1121 struct raw3270 *rp;
1122
1123 mutex_lock(&raw3270_mutex);
1124 list_for_each_entry(rp, &raw3270_devices, list)
1125 notifier->destroy(rp->minor);
1126 list_del(¬ifier->list);
1127 mutex_unlock(&raw3270_mutex);
1128 }
1129
1130
1131
1132
1133 static int
1134 raw3270_set_online (struct ccw_device *cdev)
1135 {
1136 struct raw3270_notifier *np;
1137 struct raw3270 *rp;
1138 int rc;
1139
1140 rp = raw3270_create_device(cdev);
1141 if (IS_ERR(rp))
1142 return PTR_ERR(rp);
1143 rc = raw3270_create_attributes(rp);
1144 if (rc)
1145 goto failure;
1146 raw3270_reset_device(rp);
1147 mutex_lock(&raw3270_mutex);
1148 list_for_each_entry(np, &raw3270_notifier, list)
1149 np->create(rp->minor);
1150 mutex_unlock(&raw3270_mutex);
1151 return 0;
1152
1153 failure:
1154 raw3270_delete_device(rp);
1155 return rc;
1156 }
1157
1158
1159
1160
1161 static void
1162 raw3270_remove (struct ccw_device *cdev)
1163 {
1164 unsigned long flags;
1165 struct raw3270 *rp;
1166 struct raw3270_view *v;
1167 struct raw3270_notifier *np;
1168
1169 rp = dev_get_drvdata(&cdev->dev);
1170
1171
1172
1173
1174
1175
1176 if (rp == NULL)
1177 return;
1178
1179 sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
1180
1181
1182 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
1183 if (rp->view) {
1184 if (rp->view->fn->deactivate)
1185 rp->view->fn->deactivate(rp->view);
1186 rp->view = NULL;
1187 }
1188 while (!list_empty(&rp->view_list)) {
1189 v = list_entry(rp->view_list.next, struct raw3270_view, list);
1190 if (v->fn->release)
1191 v->fn->release(v);
1192 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1193 raw3270_del_view(v);
1194 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
1195 }
1196 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1197
1198 mutex_lock(&raw3270_mutex);
1199 list_for_each_entry(np, &raw3270_notifier, list)
1200 np->destroy(rp->minor);
1201 mutex_unlock(&raw3270_mutex);
1202
1203
1204 raw3270_reset_device(rp);
1205
1206 raw3270_delete_device(rp);
1207 }
1208
1209
1210
1211
1212 static int
1213 raw3270_set_offline (struct ccw_device *cdev)
1214 {
1215 struct raw3270 *rp;
1216
1217 rp = dev_get_drvdata(&cdev->dev);
1218 if (test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags))
1219 return -EBUSY;
1220 raw3270_remove(cdev);
1221 return 0;
1222 }
1223
1224 static struct ccw_device_id raw3270_id[] = {
1225 { CCW_DEVICE(0x3270, 0) },
1226 { CCW_DEVICE(0x3271, 0) },
1227 { CCW_DEVICE(0x3272, 0) },
1228 { CCW_DEVICE(0x3273, 0) },
1229 { CCW_DEVICE(0x3274, 0) },
1230 { CCW_DEVICE(0x3275, 0) },
1231 { CCW_DEVICE(0x3276, 0) },
1232 { CCW_DEVICE(0x3277, 0) },
1233 { CCW_DEVICE(0x3278, 0) },
1234 { CCW_DEVICE(0x3279, 0) },
1235 { CCW_DEVICE(0x3174, 0) },
1236 { },
1237 };
1238
1239 static struct ccw_driver raw3270_ccw_driver = {
1240 .driver = {
1241 .name = "3270",
1242 .owner = THIS_MODULE,
1243 },
1244 .ids = raw3270_id,
1245 .probe = &raw3270_probe,
1246 .remove = &raw3270_remove,
1247 .set_online = &raw3270_set_online,
1248 .set_offline = &raw3270_set_offline,
1249 .int_class = IRQIO_C70,
1250 };
1251
1252 static int
1253 raw3270_init(void)
1254 {
1255 struct raw3270 *rp;
1256 int rc;
1257
1258 if (raw3270_registered)
1259 return 0;
1260 raw3270_registered = 1;
1261 rc = ccw_driver_register(&raw3270_ccw_driver);
1262 if (rc == 0) {
1263
1264 mutex_lock(&raw3270_mutex);
1265 class3270 = class_create(THIS_MODULE, "3270");
1266 list_for_each_entry(rp, &raw3270_devices, list) {
1267 get_device(&rp->cdev->dev);
1268 raw3270_create_attributes(rp);
1269 }
1270 mutex_unlock(&raw3270_mutex);
1271 }
1272 return rc;
1273 }
1274
1275 static void
1276 raw3270_exit(void)
1277 {
1278 ccw_driver_unregister(&raw3270_ccw_driver);
1279 class_destroy(class3270);
1280 }
1281
1282 MODULE_LICENSE("GPL");
1283
1284 module_init(raw3270_init);
1285 module_exit(raw3270_exit);
1286
1287 EXPORT_SYMBOL(class3270);
1288 EXPORT_SYMBOL(raw3270_request_alloc);
1289 EXPORT_SYMBOL(raw3270_request_free);
1290 EXPORT_SYMBOL(raw3270_request_reset);
1291 EXPORT_SYMBOL(raw3270_request_set_cmd);
1292 EXPORT_SYMBOL(raw3270_request_add_data);
1293 EXPORT_SYMBOL(raw3270_request_set_data);
1294 EXPORT_SYMBOL(raw3270_request_set_idal);
1295 EXPORT_SYMBOL(raw3270_buffer_address);
1296 EXPORT_SYMBOL(raw3270_add_view);
1297 EXPORT_SYMBOL(raw3270_del_view);
1298 EXPORT_SYMBOL(raw3270_find_view);
1299 EXPORT_SYMBOL(raw3270_activate_view);
1300 EXPORT_SYMBOL(raw3270_deactivate_view);
1301 EXPORT_SYMBOL(raw3270_start);
1302 EXPORT_SYMBOL(raw3270_start_locked);
1303 EXPORT_SYMBOL(raw3270_start_irq);
1304 EXPORT_SYMBOL(raw3270_reset);
1305 EXPORT_SYMBOL(raw3270_register_notifier);
1306 EXPORT_SYMBOL(raw3270_unregister_notifier);
1307 EXPORT_SYMBOL(raw3270_wait_queue);