xref: /openbmc/linux/drivers/s390/char/raw3270.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1 /*
2  *  drivers/s390/char/raw3270.c
3  *    IBM/3270 Driver - core functions.
4  *
5  *  Author(s):
6  *    Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
7  *    Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
8  *	-- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
9  */
10 
11 #include <linux/config.h>
12 #include <linux/bootmem.h>
13 #include <linux/module.h>
14 #include <linux/err.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/list.h>
18 #include <linux/slab.h>
19 #include <linux/types.h>
20 #include <linux/wait.h>
21 
22 #include <asm/ccwdev.h>
23 #include <asm/cio.h>
24 #include <asm/ebcdic.h>
25 
26 #include "raw3270.h"
27 
28 /* The main 3270 data structure. */
29 struct raw3270 {
30 	struct list_head list;
31 	struct ccw_device *cdev;
32 	int minor;
33 
34 	short model, rows, cols;
35 	unsigned long flags;
36 
37 	struct list_head req_queue;	/* Request queue. */
38 	struct list_head view_list;	/* List of available views. */
39 	struct raw3270_view *view;	/* Active view. */
40 
41 	struct timer_list timer;	/* Device timer. */
42 
43 	unsigned char *ascebc;		/* ascii -> ebcdic table */
44 };
45 
46 /* raw3270->flags */
47 #define RAW3270_FLAGS_14BITADDR	0	/* 14-bit buffer addresses */
48 #define RAW3270_FLAGS_BUSY	1	/* Device busy, leave it alone */
49 #define RAW3270_FLAGS_ATTN	2	/* Device sent an ATTN interrupt */
50 #define RAW3270_FLAGS_READY	4	/* Device is useable by views */
51 #define RAW3270_FLAGS_CONSOLE	8	/* Device is the console. */
52 
53 /* Semaphore to protect global data of raw3270 (devices, views, etc). */
54 static DECLARE_MUTEX(raw3270_sem);
55 
56 /* List of 3270 devices. */
57 static struct list_head raw3270_devices = LIST_HEAD_INIT(raw3270_devices);
58 
59 /*
60  * Flag to indicate if the driver has been registered. Some operations
61  * like waiting for the end of i/o need to be done differently as long
62  * as the kernel is still starting up (console support).
63  */
64 static int raw3270_registered;
65 
66 /* Module parameters */
67 static int tubxcorrect = 0;
68 module_param(tubxcorrect, bool, 0);
69 
70 /*
71  * Wait queue for device init/delete, view delete.
72  */
73 DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue);
74 
75 /*
76  * Encode array for 12 bit 3270 addresses.
77  */
78 unsigned char raw3270_ebcgraf[64] =	{
79 	0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
80 	0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
81 	0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
82 	0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
83 	0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
84 	0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
85 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
86 	0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
87 };
88 
89 void
90 raw3270_buffer_address(struct raw3270 *rp, char *cp, unsigned short addr)
91 {
92 	if (test_bit(RAW3270_FLAGS_14BITADDR, &rp->flags)) {
93 		cp[0] = (addr >> 8) & 0x3f;
94 		cp[1] = addr & 0xff;
95 	} else {
96 		cp[0] = raw3270_ebcgraf[(addr >> 6) & 0x3f];
97 		cp[1] = raw3270_ebcgraf[addr & 0x3f];
98 	}
99 }
100 
101 /*
102  * Allocate a new 3270 ccw request
103  */
104 struct raw3270_request *
105 raw3270_request_alloc(size_t size)
106 {
107 	struct raw3270_request *rq;
108 
109 	/* Allocate request structure */
110 	rq = kmalloc(sizeof(struct raw3270_request), GFP_KERNEL | GFP_DMA);
111 	if (!rq)
112 		return ERR_PTR(-ENOMEM);
113 	memset(rq, 0, sizeof(struct raw3270_request));
114 
115 	/* alloc output buffer. */
116 	if (size > 0) {
117 		rq->buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
118 		if (!rq->buffer) {
119 			kfree(rq);
120 			return ERR_PTR(-ENOMEM);
121 		}
122 	}
123 	rq->size = size;
124 	INIT_LIST_HEAD(&rq->list);
125 
126 	/*
127 	 * Setup ccw.
128 	 */
129 	rq->ccw.cda = __pa(rq->buffer);
130 	rq->ccw.flags = CCW_FLAG_SLI;
131 
132 	return rq;
133 }
134 
135 #ifdef CONFIG_TN3270_CONSOLE
136 /*
137  * Allocate a new 3270 ccw request from bootmem. Only works very
138  * early in the boot process. Only con3270.c should be using this.
139  */
140 struct raw3270_request *
141 raw3270_request_alloc_bootmem(size_t size)
142 {
143 	struct raw3270_request *rq;
144 
145 	rq = alloc_bootmem_low(sizeof(struct raw3270));
146 	if (!rq)
147 		return ERR_PTR(-ENOMEM);
148 	memset(rq, 0, sizeof(struct raw3270_request));
149 
150 	/* alloc output buffer. */
151 	if (size > 0) {
152 		rq->buffer = alloc_bootmem_low(size);
153 		if (!rq->buffer) {
154 			free_bootmem((unsigned long) rq,
155 				     sizeof(struct raw3270));
156 			return ERR_PTR(-ENOMEM);
157 		}
158 	}
159 	rq->size = size;
160 	INIT_LIST_HEAD(&rq->list);
161 
162 	/*
163 	 * Setup ccw.
164 	 */
165 	rq->ccw.cda = __pa(rq->buffer);
166 	rq->ccw.flags = CCW_FLAG_SLI;
167 
168 	return rq;
169 }
170 #endif
171 
172 /*
173  * Free 3270 ccw request
174  */
175 void
176 raw3270_request_free (struct raw3270_request *rq)
177 {
178 	if (rq->buffer)
179 		kfree(rq->buffer);
180 	kfree(rq);
181 }
182 
183 /*
184  * Reset request to initial state.
185  */
186 void
187 raw3270_request_reset(struct raw3270_request *rq)
188 {
189 	BUG_ON(!list_empty(&rq->list));
190 	rq->ccw.cmd_code = 0;
191 	rq->ccw.count = 0;
192 	rq->ccw.cda = __pa(rq->buffer);
193 	rq->ccw.flags = CCW_FLAG_SLI;
194 	rq->rescnt = 0;
195 	rq->rc = 0;
196 }
197 
198 /*
199  * Set command code to ccw of a request.
200  */
201 void
202 raw3270_request_set_cmd(struct raw3270_request *rq, u8 cmd)
203 {
204 	rq->ccw.cmd_code = cmd;
205 }
206 
207 /*
208  * Add data fragment to output buffer.
209  */
210 int
211 raw3270_request_add_data(struct raw3270_request *rq, void *data, size_t size)
212 {
213 	if (size + rq->ccw.count > rq->size)
214 		return -E2BIG;
215 	memcpy(rq->buffer + rq->ccw.count, data, size);
216 	rq->ccw.count += size;
217 	return 0;
218 }
219 
220 /*
221  * Set address/length pair to ccw of a request.
222  */
223 void
224 raw3270_request_set_data(struct raw3270_request *rq, void *data, size_t size)
225 {
226 	rq->ccw.cda = __pa(data);
227 	rq->ccw.count = size;
228 }
229 
230 /*
231  * Set idal buffer to ccw of a request.
232  */
233 void
234 raw3270_request_set_idal(struct raw3270_request *rq, struct idal_buffer *ib)
235 {
236 	rq->ccw.cda = __pa(ib->data);
237 	rq->ccw.count = ib->size;
238 	rq->ccw.flags |= CCW_FLAG_IDA;
239 }
240 
241 /*
242  * Stop running ccw.
243  */
244 static int
245 raw3270_halt_io_nolock(struct raw3270 *rp, struct raw3270_request *rq)
246 {
247 	int retries;
248 	int rc;
249 
250 	if (raw3270_request_final(rq))
251 		return 0;
252 	/* Check if interrupt has already been processed */
253 	for (retries = 0; retries < 5; retries++) {
254 		if (retries < 2)
255 			rc = ccw_device_halt(rp->cdev, (long) rq);
256 		else
257 			rc = ccw_device_clear(rp->cdev, (long) rq);
258 		if (rc == 0)
259 			break;		/* termination successful */
260 	}
261 	return rc;
262 }
263 
264 static int
265 raw3270_halt_io(struct raw3270 *rp, struct raw3270_request *rq)
266 {
267 	unsigned long flags;
268 	int rc;
269 
270 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
271 	rc = raw3270_halt_io_nolock(rp, rq);
272 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
273 	return rc;
274 }
275 
276 /*
277  * Add the request to the request queue, try to start it if the
278  * 3270 device is idle. Return without waiting for end of i/o.
279  */
280 static int
281 __raw3270_start(struct raw3270 *rp, struct raw3270_view *view,
282 		struct raw3270_request *rq)
283 {
284 	rq->view = view;
285 	raw3270_get_view(view);
286 	if (list_empty(&rp->req_queue) &&
287 	    !test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
288 		/* No other requests are on the queue. Start this one. */
289 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
290 					       (unsigned long) rq, 0, 0);
291 		if (rq->rc) {
292 			raw3270_put_view(view);
293 			return rq->rc;
294 		}
295 	}
296 	list_add_tail(&rq->list, &rp->req_queue);
297 	return 0;
298 }
299 
300 int
301 raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
302 {
303 	unsigned long flags;
304 	struct raw3270 *rp;
305 	int rc;
306 
307 	spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
308 	rp = view->dev;
309 	if (!rp || rp->view != view)
310 		rc = -EACCES;
311 	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
312 		rc = -ENODEV;
313 	else
314 		rc =  __raw3270_start(rp, view, rq);
315 	spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
316 	return rc;
317 }
318 
319 int
320 raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
321 {
322 	struct raw3270 *rp;
323 
324 	rp = view->dev;
325 	rq->view = view;
326 	raw3270_get_view(view);
327 	list_add_tail(&rq->list, &rp->req_queue);
328 	return 0;
329 }
330 
331 /*
332  * 3270 interrupt routine, called from the ccw_device layer
333  */
334 static void
335 raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
336 {
337 	struct raw3270 *rp;
338 	struct raw3270_view *view;
339 	struct raw3270_request *rq;
340 	int rc;
341 
342 	rp = (struct raw3270 *) cdev->dev.driver_data;
343 	if (!rp)
344 		return;
345 	rq = (struct raw3270_request *) intparm;
346 	view = rq ? rq->view : rp->view;
347 
348 	if (IS_ERR(irb))
349 		rc = RAW3270_IO_RETRY;
350 	else if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
351 		rq->rc = -EIO;
352 		rc = RAW3270_IO_DONE;
353 	} else if (irb->scsw.dstat ==  (DEV_STAT_CHN_END | DEV_STAT_DEV_END |
354 					DEV_STAT_UNIT_EXCEP)) {
355 		/* Handle CE-DE-UE and subsequent UDE */
356 		set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
357 		rc = RAW3270_IO_BUSY;
358 	} else if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
359 		/* Wait for UDE if busy flag is set. */
360 		if (irb->scsw.dstat & DEV_STAT_DEV_END) {
361 			clear_bit(RAW3270_FLAGS_BUSY, &rp->flags);
362 			/* Got it, now retry. */
363 			rc = RAW3270_IO_RETRY;
364 		} else
365 			rc = RAW3270_IO_BUSY;
366 	} else if (view)
367 		rc = view->fn->intv(view, rq, irb);
368 	else
369 		rc = RAW3270_IO_DONE;
370 
371 	switch (rc) {
372 	case RAW3270_IO_DONE:
373 		break;
374 	case RAW3270_IO_BUSY:
375 		/*
376 		 * Intervention required by the operator. We have to wait
377 		 * for unsolicited device end.
378 		 */
379 		return;
380 	case RAW3270_IO_RETRY:
381 		if (!rq)
382 			break;
383 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
384 					  (unsigned long) rq, 0, 0);
385 		if (rq->rc == 0)
386 			return;	/* Sucessfully restarted. */
387 		break;
388 	case RAW3270_IO_STOP:
389 		if (!rq)
390 			break;
391 		raw3270_halt_io_nolock(rp, rq);
392 		rq->rc = -EIO;
393 		break;
394 	default:
395 		BUG();
396 	}
397 	if (rq) {
398 		BUG_ON(list_empty(&rq->list));
399 		/* The request completed, remove from queue and do callback. */
400 		list_del_init(&rq->list);
401 		if (rq->callback)
402 			rq->callback(rq, rq->callback_data);
403 		/* Do put_device for get_device in raw3270_start. */
404 		raw3270_put_view(view);
405 	}
406 	/*
407 	 * Try to start each request on request queue until one is
408 	 * started successful.
409 	 */
410 	while (!list_empty(&rp->req_queue)) {
411 		rq = list_entry(rp->req_queue.next,struct raw3270_request,list);
412 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
413 					  (unsigned long) rq, 0, 0);
414 		if (rq->rc == 0)
415 			break;
416 		/* Start failed. Remove request and do callback. */
417 		list_del_init(&rq->list);
418 		if (rq->callback)
419 			rq->callback(rq, rq->callback_data);
420 		/* Do put_device for get_device in raw3270_start. */
421 		raw3270_put_view(view);
422 	}
423 }
424 
425 /*
426  * Size sensing.
427  */
428 
429 struct raw3270_ua {	/* Query Reply structure for Usable Area */
430 	struct {	/* Usable Area Query Reply Base */
431 		short l;	/* Length of this structured field */
432 		char  sfid;	/* 0x81 if Query Reply */
433 		char  qcode;	/* 0x81 if Usable Area */
434 		char  flags0;
435 		char  flags1;
436 		short w;	/* Width of usable area */
437 		short h;	/* Heigth of usavle area */
438 		char  units;	/* 0x00:in; 0x01:mm */
439 		int   xr;
440 		int   yr;
441 		char  aw;
442 		char  ah;
443 		short buffsz;	/* Character buffer size, bytes */
444 		char  xmin;
445 		char  ymin;
446 		char  xmax;
447 		char  ymax;
448 	} __attribute__ ((packed)) uab;
449 	struct {	/* Alternate Usable Area Self-Defining Parameter */
450 		char  l;	/* Length of this Self-Defining Parm */
451 		char  sdpid;	/* 0x02 if Alternate Usable Area */
452 		char  res;
453 		char  auaid;	/* 0x01 is Id for the A U A */
454 		short wauai;	/* Width of AUAi */
455 		short hauai;	/* Height of AUAi */
456 		char  auaunits;	/* 0x00:in, 0x01:mm */
457 		int   auaxr;
458 		int   auayr;
459 		char  awauai;
460 		char  ahauai;
461 	} __attribute__ ((packed)) aua;
462 } __attribute__ ((packed));
463 
464 static unsigned char raw3270_init_data[256];
465 static struct raw3270_request raw3270_init_request;
466 static struct diag210 raw3270_init_diag210;
467 static DECLARE_MUTEX(raw3270_init_sem);
468 
469 static int
470 raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
471 		 struct irb *irb)
472 {
473 	/*
474 	 * Unit-Check Processing:
475 	 * Expect Command Reject or Intervention Required.
476 	 */
477 	if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
478 		/* Request finished abnormally. */
479 		if (irb->ecw[0] & SNS0_INTERVENTION_REQ) {
480 			set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags);
481 			return RAW3270_IO_BUSY;
482 		}
483 	}
484 	if (rq) {
485 		if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
486 			if (irb->ecw[0] & SNS0_CMD_REJECT)
487 				rq->rc = -EOPNOTSUPP;
488 			else
489 				rq->rc = -EIO;
490 		} else
491 			/* Request finished normally. Copy residual count. */
492 			rq->rescnt = irb->scsw.count;
493 	}
494 	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
495 		set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags);
496 		wake_up(&raw3270_wait_queue);
497 	}
498 	return RAW3270_IO_DONE;
499 }
500 
501 static struct raw3270_fn raw3270_init_fn = {
502 	.intv = raw3270_init_irq
503 };
504 
505 static struct raw3270_view raw3270_init_view = {
506 	.fn = &raw3270_init_fn
507 };
508 
509 /*
510  * raw3270_wait/raw3270_wait_interruptible/__raw3270_wakeup
511  * Wait for end of request. The request must have been started
512  * with raw3270_start, rc = 0. The device lock may NOT have been
513  * released between calling raw3270_start and raw3270_wait.
514  */
515 static void
516 raw3270_wake_init(struct raw3270_request *rq, void *data)
517 {
518 	wake_up((wait_queue_head_t *) data);
519 }
520 
521 /*
522  * Special wait function that can cope with console initialization.
523  */
524 static int
525 raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
526 		   struct raw3270_request *rq)
527 {
528 	unsigned long flags;
529 	wait_queue_head_t wq;
530 	int rc;
531 
532 #ifdef CONFIG_TN3270_CONSOLE
533 	if (raw3270_registered == 0) {
534 		spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
535 		rq->callback = 0;
536 		rc = __raw3270_start(rp, view, rq);
537 		if (rc == 0)
538 			while (!raw3270_request_final(rq)) {
539 				wait_cons_dev();
540 				barrier();
541 			}
542 		spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
543 		return rq->rc;
544 	}
545 #endif
546 	init_waitqueue_head(&wq);
547 	rq->callback = raw3270_wake_init;
548 	rq->callback_data = &wq;
549 	spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
550 	rc = __raw3270_start(rp, view, rq);
551 	spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
552 	if (rc)
553 		return rc;
554 	/* Now wait for the completion. */
555 	rc = wait_event_interruptible(wq, raw3270_request_final(rq));
556 	if (rc == -ERESTARTSYS) {	/* Interrupted by a signal. */
557 		raw3270_halt_io(view->dev, rq);
558 		/* No wait for the halt to complete. */
559 		wait_event(wq, raw3270_request_final(rq));
560 		return -ERESTARTSYS;
561 	}
562 	return rq->rc;
563 }
564 
565 static int
566 __raw3270_size_device_vm(struct raw3270 *rp)
567 {
568 	int rc, model;
569 
570 	raw3270_init_diag210.vrdcdvno =
571 		_ccw_device_get_device_number(rp->cdev);
572 	raw3270_init_diag210.vrdclen = sizeof(struct diag210);
573 	rc = diag210(&raw3270_init_diag210);
574 	if (rc)
575 		return rc;
576 	model = raw3270_init_diag210.vrdccrmd;
577 	switch (model) {
578 	case 2:
579 		rp->model = model;
580 		rp->rows = 24;
581 		rp->cols = 80;
582 		break;
583 	case 3:
584 		rp->model = model;
585 		rp->rows = 32;
586 		rp->cols = 80;
587 		break;
588 	case 4:
589 		rp->model = model;
590 		rp->rows = 43;
591 		rp->cols = 80;
592 		break;
593 	case 5:
594 		rp->model = model;
595 		rp->rows = 27;
596 		rp->cols = 132;
597 		break;
598 	default:
599 		printk(KERN_WARNING "vrdccrmd is 0x%.8x\n", model);
600 		rc = -EOPNOTSUPP;
601 		break;
602 	}
603 	return rc;
604 }
605 
606 static int
607 __raw3270_size_device(struct raw3270 *rp)
608 {
609 	static const unsigned char wbuf[] =
610 		{ 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };
611 	struct raw3270_ua *uap;
612 	unsigned short count;
613 	int rc;
614 
615 	/*
616 	 * To determine the size of the 3270 device we need to do:
617 	 * 1) send a 'read partition' data stream to the device
618 	 * 2) wait for the attn interrupt that preceeds the query reply
619 	 * 3) do a read modified to get the query reply
620 	 * To make things worse we have to cope with intervention
621 	 * required (3270 device switched to 'stand-by') and command
622 	 * rejects (old devices that can't do 'read partition').
623 	 */
624 	memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));
625 	memset(raw3270_init_data, 0, sizeof(raw3270_init_data));
626 	/* Store 'read partition' data stream to raw3270_init_data */
627 	memcpy(raw3270_init_data, wbuf, sizeof(wbuf));
628 	INIT_LIST_HEAD(&raw3270_init_request.list);
629 	raw3270_init_request.ccw.cmd_code = TC_WRITESF;
630 	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
631 	raw3270_init_request.ccw.count = sizeof(wbuf);
632 	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
633 
634 	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
635 	if (rc) {
636 		/* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */
637 		if (rc == -EOPNOTSUPP && MACHINE_IS_VM)
638 			return __raw3270_size_device_vm(rp);
639 		return rc;
640 	}
641 
642 	/* Wait for attention interrupt. */
643 #ifdef CONFIG_TN3270_CONSOLE
644 	if (raw3270_registered == 0) {
645 		unsigned long flags;
646 
647 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
648 		while (!test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags))
649 			wait_cons_dev();
650 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
651 	} else
652 #endif
653 		rc = wait_event_interruptible(raw3270_wait_queue,
654 			test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags));
655 	if (rc)
656 		return rc;
657 
658 	/*
659 	 * The device accepted the 'read partition' command. Now
660 	 * set up a read ccw and issue it.
661 	 */
662 	raw3270_init_request.ccw.cmd_code = TC_READMOD;
663 	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
664 	raw3270_init_request.ccw.count = sizeof(raw3270_init_data);
665 	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
666 	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
667 	if (rc)
668 		return rc;
669 	/* Got a Query Reply */
670 	count = sizeof(raw3270_init_data) - raw3270_init_request.rescnt;
671 	uap = (struct raw3270_ua *) (raw3270_init_data + 1);
672 	/* Paranoia check. */
673 	if (raw3270_init_data[0] != 0x88 || uap->uab.qcode != 0x81)
674 		return -EOPNOTSUPP;
675 	/* Copy rows/columns of default Usable Area */
676 	rp->rows = uap->uab.h;
677 	rp->cols = uap->uab.w;
678 	/* Check for 14 bit addressing */
679 	if ((uap->uab.flags0 & 0x0d) == 0x01)
680 		set_bit(RAW3270_FLAGS_14BITADDR, &rp->flags);
681 	/* Check for Alternate Usable Area */
682 	if (uap->uab.l == sizeof(struct raw3270_ua) &&
683 	    uap->aua.sdpid == 0x02) {
684 		rp->rows = uap->aua.hauai;
685 		rp->cols = uap->aua.wauai;
686 	}
687 	return 0;
688 }
689 
690 static int
691 raw3270_size_device(struct raw3270 *rp)
692 {
693 	int rc;
694 
695 	down(&raw3270_init_sem);
696 	rp->view = &raw3270_init_view;
697 	raw3270_init_view.dev = rp;
698 	rc = __raw3270_size_device(rp);
699 	raw3270_init_view.dev = 0;
700 	rp->view = 0;
701 	up(&raw3270_init_sem);
702 	if (rc == 0) {	/* Found something. */
703 		/* Try to find a model. */
704 		rp->model = 0;
705 		if (rp->rows == 24 && rp->cols == 80)
706 			rp->model = 2;
707 		if (rp->rows == 32 && rp->cols == 80)
708 			rp->model = 3;
709 		if (rp->rows == 43 && rp->cols == 80)
710 			rp->model = 4;
711 		if (rp->rows == 27 && rp->cols == 132)
712 			rp->model = 5;
713 	}
714 	return rc;
715 }
716 
717 static int
718 raw3270_reset_device(struct raw3270 *rp)
719 {
720 	int rc;
721 
722 	down(&raw3270_init_sem);
723 	memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));
724 	memset(raw3270_init_data, 0, sizeof(raw3270_init_data));
725 	/* Store reset data stream to raw3270_init_data/raw3270_init_request */
726 	raw3270_init_data[0] = TW_KR;
727 	INIT_LIST_HEAD(&raw3270_init_request.list);
728 	raw3270_init_request.ccw.cmd_code = TC_EWRITEA;
729 	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
730 	raw3270_init_request.ccw.count = 1;
731 	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
732 	rp->view = &raw3270_init_view;
733 	raw3270_init_view.dev = rp;
734 	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
735 	raw3270_init_view.dev = 0;
736 	rp->view = 0;
737 	up(&raw3270_init_sem);
738 	return rc;
739 }
740 
741 /*
742  * Setup new 3270 device.
743  */
744 static int
745 raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
746 {
747 	struct list_head *l;
748 	struct raw3270 *tmp;
749 	int minor;
750 
751 	memset(rp, 0, sizeof(struct raw3270));
752 	/* Copy ebcdic -> ascii translation table. */
753 	memcpy(ascebc, _ascebc, 256);
754 	if (tubxcorrect) {
755 		/* correct brackets and circumflex */
756 		ascebc['['] = 0xad;
757 		ascebc[']'] = 0xbd;
758 		ascebc['^'] = 0xb0;
759 	}
760 	rp->ascebc = ascebc;
761 
762 	/* Set defaults. */
763 	rp->rows = 24;
764 	rp->cols = 80;
765 
766 	INIT_LIST_HEAD(&rp->req_queue);
767 	INIT_LIST_HEAD(&rp->view_list);
768 
769 	/*
770 	 * Add device to list and find the smallest unused minor
771 	 * number for it.
772 	 */
773 	down(&raw3270_sem);
774 	/* Keep the list sorted. */
775 	minor = 0;
776 	rp->minor = -1;
777 	list_for_each(l, &raw3270_devices) {
778 		tmp = list_entry(l, struct raw3270, list);
779 		if (tmp->minor > minor) {
780 			rp->minor = minor;
781 			__list_add(&rp->list, l->prev, l);
782 			break;
783 		}
784 		minor++;
785 	}
786 	if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {
787 		rp->minor = minor;
788 		list_add_tail(&rp->list, &raw3270_devices);
789 	}
790 	up(&raw3270_sem);
791 	/* No free minor number? Then give up. */
792 	if (rp->minor == -1)
793 		return -EUSERS;
794 	rp->cdev = cdev;
795 	cdev->dev.driver_data = rp;
796 	cdev->handler = raw3270_irq;
797 	return 0;
798 }
799 
800 #ifdef CONFIG_TN3270_CONSOLE
801 /*
802  * Setup 3270 device configured as console.
803  */
804 struct raw3270 *
805 raw3270_setup_console(struct ccw_device *cdev)
806 {
807 	struct raw3270 *rp;
808 	char *ascebc;
809 	int rc;
810 
811 	rp = (struct raw3270 *) alloc_bootmem(sizeof(struct raw3270));
812 	ascebc = (char *) alloc_bootmem(256);
813 	rc = raw3270_setup_device(cdev, rp, ascebc);
814 	if (rc)
815 		return ERR_PTR(rc);
816 	set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
817 	rc = raw3270_reset_device(rp);
818 	if (rc)
819 		return ERR_PTR(rc);
820 	rc = raw3270_size_device(rp);
821 	if (rc)
822 		return ERR_PTR(rc);
823 	rc = raw3270_reset_device(rp);
824 	if (rc)
825 		return ERR_PTR(rc);
826 	set_bit(RAW3270_FLAGS_READY, &rp->flags);
827 	return rp;
828 }
829 
830 void
831 raw3270_wait_cons_dev(struct raw3270 *rp)
832 {
833 	unsigned long flags;
834 
835 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
836 	wait_cons_dev();
837 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
838 }
839 
840 #endif
841 
842 /*
843  * Create a 3270 device structure.
844  */
845 static struct raw3270 *
846 raw3270_create_device(struct ccw_device *cdev)
847 {
848 	struct raw3270 *rp;
849 	char *ascebc;
850 	int rc;
851 
852 	rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL);
853 	if (!rp)
854 		return ERR_PTR(-ENOMEM);
855 	ascebc = kmalloc(256, GFP_KERNEL);
856 	if (!ascebc) {
857 		kfree(rp);
858 		return ERR_PTR(-ENOMEM);
859 	}
860 	rc = raw3270_setup_device(cdev, rp, ascebc);
861 	if (rc) {
862 		kfree(rp->ascebc);
863 		kfree(rp);
864 		rp = ERR_PTR(rc);
865 	}
866 	/* Get reference to ccw_device structure. */
867 	get_device(&cdev->dev);
868 	return rp;
869 }
870 
871 /*
872  * Activate a view.
873  */
874 int
875 raw3270_activate_view(struct raw3270_view *view)
876 {
877 	struct raw3270 *rp;
878 	struct raw3270_view *oldview, *nv;
879 	unsigned long flags;
880 	int rc;
881 
882 	rp = view->dev;
883 	if (!rp)
884 		return -ENODEV;
885 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
886 	if (rp->view == view)
887 		rc = 0;
888 	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
889 		rc = -ENODEV;
890 	else {
891 		oldview = 0;
892 		if (rp->view) {
893 			oldview = rp->view;
894 			oldview->fn->deactivate(oldview);
895 		}
896 		rp->view = view;
897 		rc = view->fn->activate(view);
898 		if (rc) {
899 			/* Didn't work. Try to reactivate the old view. */
900 			rp->view = oldview;
901 			if (!oldview || oldview->fn->activate(oldview) != 0) {
902 				/* Didn't work as well. Try any other view. */
903 				list_for_each_entry(nv, &rp->view_list, list)
904 					if (nv != view && nv != oldview) {
905 						rp->view = nv;
906 						if (nv->fn->activate(nv) == 0)
907 							break;
908 						rp->view = 0;
909 					}
910 			}
911 		}
912 	}
913 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
914 	return rc;
915 }
916 
917 /*
918  * Deactivate current view.
919  */
920 void
921 raw3270_deactivate_view(struct raw3270_view *view)
922 {
923 	unsigned long flags;
924 	struct raw3270 *rp;
925 
926 	rp = view->dev;
927 	if (!rp)
928 		return;
929 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
930 	if (rp->view == view) {
931 		view->fn->deactivate(view);
932 		rp->view = 0;
933 		/* Move deactivated view to end of list. */
934 		list_del_init(&view->list);
935 		list_add_tail(&view->list, &rp->view_list);
936 		/* Try to activate another view. */
937 		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
938 			list_for_each_entry(view, &rp->view_list, list)
939 				if (view->fn->activate(view) == 0) {
940 					rp->view = view;
941 					break;
942 				}
943 		}
944 	}
945 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
946 }
947 
948 /*
949  * Add view to device with minor "minor".
950  */
951 int
952 raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
953 {
954 	unsigned long flags;
955 	struct raw3270 *rp;
956 	int rc;
957 
958 	down(&raw3270_sem);
959 	rc = -ENODEV;
960 	list_for_each_entry(rp, &raw3270_devices, list) {
961 		if (rp->minor != minor)
962 			continue;
963 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
964 		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
965 			atomic_set(&view->ref_count, 2);
966 			view->dev = rp;
967 			view->fn = fn;
968 			view->model = rp->model;
969 			view->rows = rp->rows;
970 			view->cols = rp->cols;
971 			view->ascebc = rp->ascebc;
972 			spin_lock_init(&view->lock);
973 			list_add_tail(&view->list, &rp->view_list);
974 			rc = 0;
975 		}
976 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
977 		break;
978 	}
979 	up(&raw3270_sem);
980 	return rc;
981 }
982 
983 /*
984  * Find specific view of device with minor "minor".
985  */
986 struct raw3270_view *
987 raw3270_find_view(struct raw3270_fn *fn, int minor)
988 {
989 	struct raw3270 *rp;
990 	struct raw3270_view *view, *tmp;
991 	unsigned long flags;
992 
993 	down(&raw3270_sem);
994 	view = ERR_PTR(-ENODEV);
995 	list_for_each_entry(rp, &raw3270_devices, list) {
996 		if (rp->minor != minor)
997 			continue;
998 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
999 		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
1000 			view = ERR_PTR(-ENOENT);
1001 			list_for_each_entry(tmp, &rp->view_list, list) {
1002 				if (tmp->fn == fn) {
1003 					raw3270_get_view(tmp);
1004 					view = tmp;
1005 					break;
1006 				}
1007 			}
1008 		}
1009 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
1010 		break;
1011 	}
1012 	up(&raw3270_sem);
1013 	return view;
1014 }
1015 
1016 /*
1017  * Remove view from device and free view structure via call to view->fn->free.
1018  */
1019 void
1020 raw3270_del_view(struct raw3270_view *view)
1021 {
1022 	unsigned long flags;
1023 	struct raw3270 *rp;
1024 	struct raw3270_view *nv;
1025 
1026 	rp = view->dev;
1027 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
1028 	if (rp->view == view) {
1029 		view->fn->deactivate(view);
1030 		rp->view = 0;
1031 	}
1032 	list_del_init(&view->list);
1033 	if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
1034 		/* Try to activate another view. */
1035 		list_for_each_entry(nv, &rp->view_list, list) {
1036 			if (nv->fn->activate(view) == 0) {
1037 				rp->view = nv;
1038 				break;
1039 			}
1040 		}
1041 	}
1042 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
1043 	/* Wait for reference counter to drop to zero. */
1044 	atomic_dec(&view->ref_count);
1045 	wait_event(raw3270_wait_queue, atomic_read(&view->ref_count) == 0);
1046 	if (view->fn->free)
1047 		view->fn->free(view);
1048 }
1049 
1050 /*
1051  * Remove a 3270 device structure.
1052  */
1053 static void
1054 raw3270_delete_device(struct raw3270 *rp)
1055 {
1056 	struct ccw_device *cdev;
1057 
1058 	/* Remove from device chain. */
1059 	down(&raw3270_sem);
1060 	list_del_init(&rp->list);
1061 	up(&raw3270_sem);
1062 
1063 	/* Disconnect from ccw_device. */
1064 	cdev = rp->cdev;
1065 	rp->cdev = 0;
1066 	cdev->dev.driver_data = 0;
1067 	cdev->handler = 0;
1068 
1069 	/* Put ccw_device structure. */
1070 	put_device(&cdev->dev);
1071 
1072 	/* Now free raw3270 structure. */
1073 	kfree(rp->ascebc);
1074 	kfree(rp);
1075 }
1076 
1077 static int
1078 raw3270_probe (struct ccw_device *cdev)
1079 {
1080 	return 0;
1081 }
1082 
1083 /*
1084  * Additional attributes for a 3270 device
1085  */
1086 static ssize_t
1087 raw3270_model_show(struct device *dev, char *buf)
1088 {
1089 	return snprintf(buf, PAGE_SIZE, "%i\n",
1090 			((struct raw3270 *) dev->driver_data)->model);
1091 }
1092 static DEVICE_ATTR(model, 0444, raw3270_model_show, 0);
1093 
1094 static ssize_t
1095 raw3270_rows_show(struct device *dev, char *buf)
1096 {
1097 	return snprintf(buf, PAGE_SIZE, "%i\n",
1098 			((struct raw3270 *) dev->driver_data)->rows);
1099 }
1100 static DEVICE_ATTR(rows, 0444, raw3270_rows_show, 0);
1101 
1102 static ssize_t
1103 raw3270_columns_show(struct device *dev, char *buf)
1104 {
1105 	return snprintf(buf, PAGE_SIZE, "%i\n",
1106 			((struct raw3270 *) dev->driver_data)->cols);
1107 }
1108 static DEVICE_ATTR(columns, 0444, raw3270_columns_show, 0);
1109 
1110 static struct attribute * raw3270_attrs[] = {
1111 	&dev_attr_model.attr,
1112 	&dev_attr_rows.attr,
1113 	&dev_attr_columns.attr,
1114 	NULL,
1115 };
1116 
1117 static struct attribute_group raw3270_attr_group = {
1118 	.attrs = raw3270_attrs,
1119 };
1120 
1121 static void
1122 raw3270_create_attributes(struct raw3270 *rp)
1123 {
1124 	//FIXME: check return code
1125 	sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
1126 }
1127 
1128 /*
1129  * Notifier for device addition/removal
1130  */
1131 struct raw3270_notifier {
1132 	struct list_head list;
1133 	void (*notifier)(int, int);
1134 };
1135 
1136 static struct list_head raw3270_notifier = LIST_HEAD_INIT(raw3270_notifier);
1137 
1138 int raw3270_register_notifier(void (*notifier)(int, int))
1139 {
1140 	struct raw3270_notifier *np;
1141 	struct raw3270 *rp;
1142 
1143 	np = kmalloc(sizeof(struct raw3270_notifier), GFP_KERNEL);
1144 	if (!np)
1145 		return -ENOMEM;
1146 	np->notifier = notifier;
1147 	down(&raw3270_sem);
1148 	list_add_tail(&np->list, &raw3270_notifier);
1149 	list_for_each_entry(rp, &raw3270_devices, list) {
1150 		get_device(&rp->cdev->dev);
1151 		notifier(rp->minor, 1);
1152 	}
1153 	up(&raw3270_sem);
1154 	return 0;
1155 }
1156 
1157 void raw3270_unregister_notifier(void (*notifier)(int, int))
1158 {
1159 	struct raw3270_notifier *np;
1160 
1161 	down(&raw3270_sem);
1162 	list_for_each_entry(np, &raw3270_notifier, list)
1163 		if (np->notifier == notifier) {
1164 			list_del(&np->list);
1165 			kfree(np);
1166 			break;
1167 		}
1168 	up(&raw3270_sem);
1169 }
1170 
1171 /*
1172  * Set 3270 device online.
1173  */
1174 static int
1175 raw3270_set_online (struct ccw_device *cdev)
1176 {
1177 	struct raw3270 *rp;
1178 	struct raw3270_notifier *np;
1179 	int rc;
1180 
1181 	rp = raw3270_create_device(cdev);
1182 	if (IS_ERR(rp))
1183 		return PTR_ERR(rp);
1184 	rc = raw3270_reset_device(rp);
1185 	if (rc)
1186 		return rc;
1187 	rc = raw3270_size_device(rp);
1188 	if (rc)
1189 		return rc;
1190 	rc = raw3270_reset_device(rp);
1191 	if (rc)
1192 		return rc;
1193 	raw3270_create_attributes(rp);
1194 	set_bit(RAW3270_FLAGS_READY, &rp->flags);
1195 	down(&raw3270_sem);
1196 	list_for_each_entry(np, &raw3270_notifier, list)
1197 		np->notifier(rp->minor, 1);
1198 	up(&raw3270_sem);
1199 	return 0;
1200 }
1201 
1202 /*
1203  * Remove 3270 device structure.
1204  */
1205 static void
1206 raw3270_remove (struct ccw_device *cdev)
1207 {
1208 	unsigned long flags;
1209 	struct raw3270 *rp;
1210 	struct raw3270_view *v;
1211 	struct raw3270_notifier *np;
1212 
1213 	rp = cdev->dev.driver_data;
1214 	clear_bit(RAW3270_FLAGS_READY, &rp->flags);
1215 
1216 	sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
1217 
1218 	/* Deactivate current view and remove all views. */
1219 	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
1220 	if (rp->view) {
1221 		rp->view->fn->deactivate(rp->view);
1222 		rp->view = 0;
1223 	}
1224 	while (!list_empty(&rp->view_list)) {
1225 		v = list_entry(rp->view_list.next, struct raw3270_view, list);
1226 		if (v->fn->release)
1227 			v->fn->release(v);
1228 		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1229 		raw3270_del_view(v);
1230 		spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
1231 	}
1232 	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1233 
1234 	down(&raw3270_sem);
1235 	list_for_each_entry(np, &raw3270_notifier, list)
1236 		np->notifier(rp->minor, 0);
1237 	up(&raw3270_sem);
1238 
1239 	/* Reset 3270 device. */
1240 	raw3270_reset_device(rp);
1241 	/* And finally remove it. */
1242 	raw3270_delete_device(rp);
1243 }
1244 
1245 /*
1246  * Set 3270 device offline.
1247  */
1248 static int
1249 raw3270_set_offline (struct ccw_device *cdev)
1250 {
1251 	struct raw3270 *rp;
1252 
1253 	rp = cdev->dev.driver_data;
1254 	if (test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags))
1255 		return -EBUSY;
1256 	raw3270_remove(cdev);
1257 	return 0;
1258 }
1259 
1260 static struct ccw_device_id raw3270_id[] = {
1261 	{ CCW_DEVICE(0x3270, 0) },
1262 	{ CCW_DEVICE(0x3271, 0) },
1263 	{ CCW_DEVICE(0x3272, 0) },
1264 	{ CCW_DEVICE(0x3273, 0) },
1265 	{ CCW_DEVICE(0x3274, 0) },
1266 	{ CCW_DEVICE(0x3275, 0) },
1267 	{ CCW_DEVICE(0x3276, 0) },
1268 	{ CCW_DEVICE(0x3277, 0) },
1269 	{ CCW_DEVICE(0x3278, 0) },
1270 	{ CCW_DEVICE(0x3279, 0) },
1271 	{ CCW_DEVICE(0x3174, 0) },
1272 	{ /* end of list */ },
1273 };
1274 
1275 static struct ccw_driver raw3270_ccw_driver = {
1276 	.name		= "3270",
1277 	.owner		= THIS_MODULE,
1278 	.ids		= raw3270_id,
1279 	.probe		= &raw3270_probe,
1280 	.remove		= &raw3270_remove,
1281 	.set_online	= &raw3270_set_online,
1282 	.set_offline	= &raw3270_set_offline,
1283 };
1284 
1285 static int
1286 raw3270_init(void)
1287 {
1288 	struct raw3270 *rp;
1289 	int rc;
1290 
1291 	if (raw3270_registered)
1292 		return 0;
1293 	raw3270_registered = 1;
1294 	rc = ccw_driver_register(&raw3270_ccw_driver);
1295 	if (rc == 0) {
1296 		/* Create attributes for early (= console) device. */
1297 		down(&raw3270_sem);
1298 		list_for_each_entry(rp, &raw3270_devices, list) {
1299 			get_device(&rp->cdev->dev);
1300 			raw3270_create_attributes(rp);
1301 		}
1302 		up(&raw3270_sem);
1303 	}
1304 	return rc;
1305 }
1306 
1307 static void
1308 raw3270_exit(void)
1309 {
1310 	ccw_driver_unregister(&raw3270_ccw_driver);
1311 }
1312 
1313 MODULE_LICENSE("GPL");
1314 
1315 module_init(raw3270_init);
1316 module_exit(raw3270_exit);
1317 
1318 EXPORT_SYMBOL(raw3270_request_alloc);
1319 EXPORT_SYMBOL(raw3270_request_free);
1320 EXPORT_SYMBOL(raw3270_request_reset);
1321 EXPORT_SYMBOL(raw3270_request_set_cmd);
1322 EXPORT_SYMBOL(raw3270_request_add_data);
1323 EXPORT_SYMBOL(raw3270_request_set_data);
1324 EXPORT_SYMBOL(raw3270_request_set_idal);
1325 EXPORT_SYMBOL(raw3270_buffer_address);
1326 EXPORT_SYMBOL(raw3270_add_view);
1327 EXPORT_SYMBOL(raw3270_del_view);
1328 EXPORT_SYMBOL(raw3270_find_view);
1329 EXPORT_SYMBOL(raw3270_activate_view);
1330 EXPORT_SYMBOL(raw3270_deactivate_view);
1331 EXPORT_SYMBOL(raw3270_start);
1332 EXPORT_SYMBOL(raw3270_start_irq);
1333 EXPORT_SYMBOL(raw3270_register_notifier);
1334 EXPORT_SYMBOL(raw3270_unregister_notifier);
1335 EXPORT_SYMBOL(raw3270_wait_queue);
1336