File: /usr/src/linux/drivers/s390/char/hwc_rw.c

1     /*
2      *  drivers/s390/char/hwc_rw.c
3      *     driver: reading from and writing to system console on S/390 via HWC
4      *
5      *  S390 version
6      *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7      *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
8      *
9      * 
10      *
11      * 
12      * 
13      * 
14      */
15     
16     #include <linux/kernel.h>
17     #include <linux/string.h>
18     #include <linux/errno.h>
19     #include <linux/ctype.h>
20     #include <linux/mm.h>
21     #include <linux/timer.h>
22     #include <linux/bootmem.h>
23     #include <linux/module.h>
24     
25     #include <asm/ebcdic.h>
26     #include <asm/uaccess.h>
27     #include <asm/types.h>
28     #include <asm/bitops.h>
29     #include <asm/setup.h>
30     #include <asm/page.h>
31     #include <asm/s390_ext.h>
32     #include <asm/irq.h>
33     
34     #ifndef MIN
35     #define MIN(a,b) (((a<b) ? a : b))
36     #endif
37     
38     #define HWC_RW_PRINT_HEADER "hwc low level driver: "
39     
40     #define  USE_VM_DETECTION
41     
42     #define  DEFAULT_CASE_DELIMITER '%'
43     
44     #undef DUMP_HWC_INIT_ERROR
45     
46     #undef DUMP_HWC_WRITE_ERROR
47     
48     #undef DUMP_HWC_WRITE_LIST_ERROR
49     
50     #undef DUMP_HWC_READ_ERROR
51     
52     #undef DUMP_HWCB_INPUT
53     
54     #undef BUFFER_STRESS_TEST
55     
56     typedef struct {
57     	unsigned char *next;
58     	unsigned short int mto_char_sum;
59     	unsigned char mto_number;
60     	unsigned char times_lost;
61     	unsigned short int mto_number_lost;
62     	unsigned long int mto_char_sum_lost;
63     } __attribute__ ((packed)) 
64     
65     hwcb_list_t;
66     
67     #define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t))
68     
69     #define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t))
70     
71     #define BUF_HWCB hwc_data.hwcb_list_tail
72     #define OUT_HWCB hwc_data.hwcb_list_head
73     #define ALL_HWCB_MTO hwc_data.mto_number
74     #define ALL_HWCB_CHAR hwc_data.mto_char_sum
75     
76     #define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)]))
77     
78     #define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum)
79     
80     #define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number)
81     
82     #define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost)
83     
84     #define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost)
85     
86     #define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost)
87     
88     #define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next)
89     
90     #define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB)
91     
92     #define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB)
93     
94     #define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB)
95     
96     #define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB)
97     
98     #define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB)
99     
100     #define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB)
101     
102     #define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB)
103     
104     #define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB)
105     
106     #define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB)
107     
108     #define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB)
109     
110     #define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)
111     
112     #include  "hwc.h"
113     
114     #define __HWC_RW_C__
115     #include "hwc_rw.h"
116     #undef __HWC_RW_C__
117     
118     static unsigned char _obuf[MAX_HWCB_ROOM];
119     
120     static unsigned char
121      _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
122     
123     typedef unsigned long kmem_pages_t;
124     
125     #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
126     
127     #define HWC_WTIMER_RUNS	1
128     #define HWC_FLUSH		2
129     #define HWC_INIT		4
130     #define HWC_BROKEN		8
131     #define HWC_INTERRUPT		16
132     #define HWC_PTIMER_RUNS	32
133     
134     static struct {
135     
136     	hwc_ioctls_t ioctls;
137     
138     	hwc_ioctls_t init_ioctls;
139     
140     	unsigned char *hwcb_list_head;
141     
142     	unsigned char *hwcb_list_tail;
143     
144     	unsigned short int mto_number;
145     
146     	unsigned int mto_char_sum;
147     
148     	unsigned char hwcb_count;
149     
150     	unsigned long kmem_start;
151     
152     	unsigned long kmem_end;
153     
154     	kmem_pages_t kmem_pages;
155     
156     	unsigned char *obuf;
157     
158     	unsigned short int obuf_cursor;
159     
160     	unsigned short int obuf_count;
161     
162     	unsigned short int obuf_start;
163     
164     	unsigned char *page;
165     
166     	u32 current_servc;
167     
168     	unsigned char *current_hwcb;
169     
170     	unsigned char write_nonprio:1;
171     	unsigned char write_prio:1;
172     	unsigned char read_nonprio:1;
173     	unsigned char read_prio:1;
174     	unsigned char read_statechange:1;
175     
176     	unsigned char flags;
177     
178     	hwc_high_level_calls_t *calls;
179     
180     	hwc_request_t *request;
181     
182     	spinlock_t lock;
183     
184     	struct timer_list write_timer;
185     
186     	struct timer_list poll_timer;
187     } hwc_data =
188     {
189     	{
190     	},
191     	{
192     		8,
193     		    0,
194     		    80,
195     		    1,
196     		    MAX_KMEM_PAGES,
197     		    MAX_KMEM_PAGES,
198     
199     		    0,
200     
201     		    0x6c
202     
203     	},
204     	    NULL,
205     	    NULL,
206     	    0,
207     	    0,
208     	    0,
209     	    0,
210     	    0,
211     	    0,
212     	    _obuf,
213     	    0,
214     	    0,
215     	    0,
216     	    _page,
217     	    0,
218     	    NULL,
219     	    0,
220     	    0,
221     	    0,
222     	    0,
223     	    0,
224     	    0,
225     	    NULL,
226     	    NULL
227     
228     };
229     
230     static unsigned long cr0 __attribute__ ((aligned (8)));
231     static unsigned long cr0_save __attribute__ ((aligned (8)));
232     static unsigned char psw_mask __attribute__ ((aligned (8)));
233     
234     #define DELAYED_WRITE 0
235     #define IMMEDIATE_WRITE 1
236     
237     static signed int do_hwc_write (int from_user, unsigned char *,
238     				unsigned int,
239     				unsigned char);
240     
241     static asmlinkage int 
242     internal_print (char write_time, char *fmt,...)
243     {
244     	va_list args;
245     	int i;
246     	unsigned char buf[512];
247     
248     	va_start (args, fmt);
249     	i = vsprintf (buf, fmt, args);
250     	va_end (args);
251     	return do_hwc_write (0, buf, i, write_time);
252     }
253     
254     int 
255     hwc_printk (const char *fmt,...)
256     {
257     	va_list args;
258     	int i;
259     	unsigned char buf[512];
260     	unsigned long flags;
261     	int retval;
262     
263     	spin_lock_irqsave (&hwc_data.lock, flags);
264     
265     	i = vsprintf (buf, fmt, args);
266     	va_end (args);
267     	retval = do_hwc_write (0, buf, i, IMMEDIATE_WRITE);
268     
269     	spin_unlock_irqrestore (&hwc_data.lock, flags);
270     
271     	return retval;
272     }
273     
274     #ifdef DUMP_HWCB_INPUT
275     
276     static void 
277     dump_storage_area (unsigned char *area, unsigned short int count)
278     {
279     	unsigned short int index;
280     	ioctl_nl_t old_final_nl;
281     
282     	if (!area || !count)
283     		return;
284     
285     	old_final_nl = hwc_data.ioctls.final_nl;
286     	hwc_data.ioctls.final_nl = 1;
287     
288     	internal_print (DELAYED_WRITE, "\n%8x   ", area);
289     
290     	for (index = 0; index < count; index++) {
291     
292     		if (area[index] <= 0xF)
293     			internal_print (DELAYED_WRITE, "0%x", area[index]);
294     		else
295     			internal_print (DELAYED_WRITE, "%x", area[index]);
296     
297     		if ((index & 0xF) == 0xF)
298     			internal_print (DELAYED_WRITE, "\n%8x   ",
299     					&area[index + 1]);
300     		else if ((index & 3) == 3)
301     			internal_print (DELAYED_WRITE, " ");
302     	}
303     
304     	internal_print (IMMEDIATE_WRITE, "\n");
305     
306     	hwc_data.ioctls.final_nl = old_final_nl;
307     }
308     #endif
309     
310     static inline u32 
311     service_call (
312     		     u32 hwc_command_word,
313     		     unsigned char hwcb[])
314     {
315     	unsigned int condition_code = 1;
316     
317     	__asm__ __volatile__ ("L 1, 0(%0) \n\t"
318     			      "LRA 2, 0(%1) \n\t"
319     			      ".long 0xB2200012 \n\t"
320     			      :
321     			      :"a" (&hwc_command_word), "a" (hwcb)
322     			      :"1", "2", "memory");
323     
324     	__asm__ __volatile__ ("IPM %0 \n\t"
325     			      "SRL %0, 28 \n\t"
326     			      :"=r" (condition_code));
327     
328     	return condition_code;
329     }
330     
331     static inline unsigned long 
332     hwc_ext_int_param (void)
333     {
334     	u32 param;
335     
336     	__asm__ __volatile__ ("L %0,128\n\t"
337     			      :"=r" (param));
338     
339     	return (unsigned long) param;
340     }
341     
342     static int 
343     prepare_write_hwcb (void)
344     {
345     	write_hwcb_t *hwcb;
346     
347     	if (!BUF_HWCB)
348     		return -ENOMEM;
349     
350     	BUF_HWCB_MTO = 0;
351     	BUF_HWCB_CHAR = 0;
352     
353     	hwcb = (write_hwcb_t *) BUF_HWCB;
354     
355     	memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t));
356     
357     	return 0;
358     }
359     
360     static int 
361     sane_write_hwcb (void)
362     {
363     	unsigned short int lost_msg;
364     	unsigned int lost_char;
365     	unsigned char lost_hwcb;
366     	unsigned char *bad_addr;
367     	unsigned long page;
368     	int page_nr;
369     
370     	if (!OUT_HWCB)
371     		return -ENOMEM;
372     
373     	if ((unsigned long) OUT_HWCB & 0xFFF) {
374     
375     		bad_addr = OUT_HWCB;
376     
377     #ifdef DUMP_HWC_WRITE_LIST_ERROR
378     		__asm__ ("LHI 1,0xe30\n\t"
379     			 "LRA 2,0(%0) \n\t"
380     			 "J .+0 \n\t"
381     	      :
382     	      :	 "a" (bad_addr)
383     	      :	 "1", "2");
384     #endif
385     
386     		hwc_data.kmem_pages = 0;
387     		if ((unsigned long) BUF_HWCB & 0xFFF) {
388     
389     			lost_hwcb = hwc_data.hwcb_count;
390     			lost_msg = ALL_HWCB_MTO;
391     			lost_char = ALL_HWCB_CHAR;
392     
393     			OUT_HWCB = NULL;
394     			BUF_HWCB = NULL;
395     			ALL_HWCB_MTO = 0;
396     			ALL_HWCB_CHAR = 0;
397     			hwc_data.hwcb_count = 0;
398     		} else {
399     
400     			lost_hwcb = hwc_data.hwcb_count - 1;
401     			lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO;
402     			lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR;
403     			OUT_HWCB = BUF_HWCB;
404     			ALL_HWCB_MTO = BUF_HWCB_MTO;
405     			ALL_HWCB_CHAR = BUF_HWCB_CHAR;
406     			hwc_data.hwcb_count = 1;
407     			page = (unsigned long) BUF_HWCB;
408     
409     			if (page >= hwc_data.kmem_start &&
410     			    page <= hwc_data.kmem_end) {
411     
412     				page_nr = (int)
413     				    ((page - hwc_data.kmem_start) >> 12);
414     				set_bit (page_nr, &hwc_data.kmem_pages);
415     			}
416     		}
417     
418     		internal_print (
419     				       DELAYED_WRITE,
420     				       HWC_RW_PRINT_HEADER
421     		       "found invalid HWCB at address 0x%lx. List corrupted. "
422     			   "Lost %i HWCBs with %i characters within up to %i "
423     			   "messages. Saved %i HWCB with last %i characters i"
424     				       "within up to %i messages.\n",
425     				       (unsigned long) bad_addr,
426     				       lost_hwcb, lost_char, lost_msg,
427     				       hwc_data.hwcb_count,
428     				       ALL_HWCB_CHAR, ALL_HWCB_MTO);
429     	}
430     	return 0;
431     }
432     
433     static int 
434     reuse_write_hwcb (void)
435     {
436     	int retval;
437     
438     	if (hwc_data.hwcb_count < 2)
439     #ifdef DUMP_HWC_WRITE_LIST_ERROR
440     		__asm__ ("LHI 1,0xe31\n\t"
441     			 "LRA 2,0(%0)\n\t"
442     			 "LRA 3,0(%1)\n\t"
443     			 "J .+0 \n\t"
444     	      :
445     	      :	 "a" (BUF_HWCB), "a" (OUT_HWCB)
446     	      :	 "1", "2", "3");
447     #else
448     		return -EPERM;
449     #endif
450     
451     	if (hwc_data.current_hwcb == OUT_HWCB) {
452     
453     		if (hwc_data.hwcb_count > 2) {
454     
455     			BUF_HWCB_NEXT = OUT_HWCB_NEXT;
456     
457     			BUF_HWCB = OUT_HWCB_NEXT;
458     
459     			OUT_HWCB_NEXT = BUF_HWCB_NEXT;
460     
461     			BUF_HWCB_NEXT = NULL;
462     		}
463     	} else {
464     
465     		BUF_HWCB_NEXT = OUT_HWCB;
466     
467     		BUF_HWCB = OUT_HWCB;
468     
469     		OUT_HWCB = OUT_HWCB_NEXT;
470     
471     		BUF_HWCB_NEXT = NULL;
472     	}
473     
474     	BUF_HWCB_TIMES_LOST += 1;
475     	BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR;
476     	BUF_HWCB_MTO_LOST += BUF_HWCB_MTO;
477     	ALL_HWCB_MTO -= BUF_HWCB_MTO;
478     	ALL_HWCB_CHAR -= BUF_HWCB_CHAR;
479     
480     	retval = prepare_write_hwcb ();
481     
482     	if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
483     		internal_print (
484     				       DELAYED_WRITE,
485     				       HWC_RW_PRINT_HEADER
486     				       "reached my own limit of "
487     			    "allowed buffer space for output (%i HWCBs = %li "
488     			  "bytes), skipped content of oldest HWCB %i time(s) "
489     				       "(%i lines = %i characters)\n",
490     				       hwc_data.ioctls.max_hwcb,
491     				       hwc_data.ioctls.max_hwcb * PAGE_SIZE,
492     				       BUF_HWCB_TIMES_LOST,
493     				       BUF_HWCB_MTO_LOST,
494     				       BUF_HWCB_CHAR_LOST);
495     	else
496     		internal_print (
497     				       DELAYED_WRITE,
498     				       HWC_RW_PRINT_HEADER
499     				       "page allocation failed, "
500     			   "could not expand buffer for output (currently in "
501     			     "use: %i HWCBs = %li bytes), skipped content of "
502     			"oldest HWCB %i time(s) (%i lines = %i characters)\n",
503     				       hwc_data.hwcb_count,
504     				       hwc_data.hwcb_count * PAGE_SIZE,
505     				       BUF_HWCB_TIMES_LOST,
506     				       BUF_HWCB_MTO_LOST,
507     				       BUF_HWCB_CHAR_LOST);
508     
509     	return retval;
510     }
511     
512     static int 
513     allocate_write_hwcb (void)
514     {
515     	unsigned char *page;
516     	int page_nr;
517     
518     	if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
519     		return -ENOMEM;
520     
521     	page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES);
522     	if (page_nr < hwc_data.ioctls.kmem_hwcb) {
523     
524     		page = (unsigned char *)
525     		    (hwc_data.kmem_start + (page_nr << 12));
526     		set_bit (page_nr, &hwc_data.kmem_pages);
527     	} else
528     		page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);
529     
530     	if (!page)
531     		return -ENOMEM;
532     
533     	if (!OUT_HWCB)
534     		OUT_HWCB = page;
535     	else
536     		BUF_HWCB_NEXT = page;
537     
538     	BUF_HWCB = page;
539     
540     	BUF_HWCB_NEXT = NULL;
541     
542     	hwc_data.hwcb_count++;
543     
544     	prepare_write_hwcb ();
545     
546     	BUF_HWCB_TIMES_LOST = 0;
547     	BUF_HWCB_MTO_LOST = 0;
548     	BUF_HWCB_CHAR_LOST = 0;
549     
550     #ifdef BUFFER_STRESS_TEST
551     
552     	internal_print (
553     			       DELAYED_WRITE,
554     			       "*** " HWC_RW_PRINT_HEADER
555     			    "page #%i at 0x%x for buffering allocated. ***\n",
556     			       hwc_data.hwcb_count, page);
557     
558     #endif
559     
560     	return 0;
561     }
562     
563     static int 
564     release_write_hwcb (void)
565     {
566     	unsigned long page;
567     	int page_nr;
568     
569     	if (!hwc_data.hwcb_count)
570     		return -ENODATA;
571     
572     	if (hwc_data.hwcb_count == 1) {
573     
574     		prepare_write_hwcb ();
575     
576     		ALL_HWCB_CHAR = 0;
577     		ALL_HWCB_MTO = 0;
578     		BUF_HWCB_TIMES_LOST = 0;
579     		BUF_HWCB_MTO_LOST = 0;
580     		BUF_HWCB_CHAR_LOST = 0;
581     	} else {
582     		page = (unsigned long) OUT_HWCB;
583     
584     		ALL_HWCB_MTO -= OUT_HWCB_MTO;
585     		ALL_HWCB_CHAR -= OUT_HWCB_CHAR;
586     		hwc_data.hwcb_count--;
587     
588     		OUT_HWCB = OUT_HWCB_NEXT;
589     
590     		if (page >= hwc_data.kmem_start &&
591     		    page <= hwc_data.kmem_end) {
592     			/*memset((void *) page, 0, PAGE_SIZE); */
593     
594     			page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
595     			clear_bit (page_nr, &hwc_data.kmem_pages);
596     		} else
597     			free_page (page);
598     #ifdef BUFFER_STRESS_TEST
599     
600     		internal_print (
601     				       DELAYED_WRITE,
602     				       "*** " HWC_RW_PRINT_HEADER
603     			 "page at 0x%x released, %i pages still in use ***\n",
604     				       page, hwc_data.hwcb_count);
605     
606     #endif
607     	}
608     	return 0;
609     }
610     
611     static int 
612     add_mto (
613     		unsigned char *message,
614     		unsigned short int count)
615     {
616     	unsigned short int mto_size;
617     	write_hwcb_t *hwcb;
618     	mto_t *mto;
619     	void *dest;
620     
621     	if (!BUF_HWCB)
622     		return -ENOMEM;
623     
624     	if (BUF_HWCB == hwc_data.current_hwcb)
625     		return -ENOMEM;
626     
627     	mto_size = sizeof (mto_t) + count;
628     
629     	hwcb = (write_hwcb_t *) BUF_HWCB;
630     
631     	if ((MAX_HWCB_ROOM - hwcb->length) < mto_size)
632     		return -ENOMEM;
633     
634     	mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length);
635     
636     	memcpy (mto, &mto_template, sizeof (mto_t));
637     
638     	dest = (void *) (((unsigned long) mto) + sizeof (mto_t));
639     
640     	memcpy (dest, message, count);
641     
642     	mto->length += count;
643     
644     	hwcb->length += mto_size;
645     	hwcb->msgbuf.length += mto_size;
646     	hwcb->msgbuf.mdb.length += mto_size;
647     
648     	BUF_HWCB_MTO++;
649     	ALL_HWCB_MTO++;
650     	BUF_HWCB_CHAR += count;
651     	ALL_HWCB_CHAR += count;
652     
653     	return count;
654     }
655     
656     static int write_event_data_1 (void);
657     
658     static void 
659     do_poll_hwc (unsigned long data)
660     {
661     	unsigned long flags;
662     
663     	spin_lock_irqsave (&hwc_data.lock, flags);
664     
665     	write_event_data_1 ();
666     
667     	spin_unlock_irqrestore (&hwc_data.lock, flags);
668     }
669     
670     void 
671     start_poll_hwc (void)
672     {
673     	init_timer (&hwc_data.poll_timer);
674     	hwc_data.poll_timer.function = do_poll_hwc;
675     	hwc_data.poll_timer.data = (unsigned long) NULL;
676     	hwc_data.poll_timer.expires = jiffies + 2 * HZ;
677     	add_timer (&hwc_data.poll_timer);
678     	hwc_data.flags |= HWC_PTIMER_RUNS;
679     }
680     
681     static int 
682     write_event_data_1 (void)
683     {
684     	unsigned short int condition_code;
685     	int retval;
686     	write_hwcb_t *hwcb = (write_hwcb_t *) OUT_HWCB;
687     
688     	if ((!hwc_data.write_prio) &&
689     	    (!hwc_data.write_nonprio) &&
690     	    hwc_data.read_statechange)
691     		return -EOPNOTSUPP;
692     
693     	if (hwc_data.current_servc)
694     		return -EBUSY;
695     
696     	retval = sane_write_hwcb ();
697     	if (retval < 0)
698     		return -EIO;
699     
700     	if (!OUT_HWCB_MTO)
701     		return -ENODATA;
702     
703     	if (!hwc_data.write_nonprio && hwc_data.write_prio)
704     		hwcb->msgbuf.type = ET_PMsgCmd;
705     	else
706     		hwcb->msgbuf.type = ET_Msg;
707     
708     	condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB);
709     
710     #ifdef DUMP_HWC_WRITE_ERROR
711     	if (condition_code != HWC_COMMAND_INITIATED)
712     		__asm__ ("LHI 1,0xe20\n\t"
713     			 "L 2,0(%0)\n\t"
714     			 "LRA 3,0(%1)\n\t"
715     			 "J .+0 \n\t"
716     	      :
717     	      :	 "a" (&condition_code), "a" (OUT_HWCB)
718     	      :	 "1", "2", "3");
719     #endif
720     
721     	switch (condition_code) {
722     	case HWC_COMMAND_INITIATED:
723     		hwc_data.current_servc = HWC_CMDW_WRITEDATA;
724     		hwc_data.current_hwcb = OUT_HWCB;
725     		retval = condition_code;
726     		break;
727     	case HWC_BUSY:
728     		retval = -EBUSY;
729     		break;
730     	case HWC_NOT_OPERATIONAL:
731     		start_poll_hwc ();
732     	default:
733     		retval = -EIO;
734     	}
735     
736     	return retval;
737     }
738     
739     static void 
740     flush_hwcbs (void)
741     {
742     	while (hwc_data.hwcb_count > 1)
743     		release_write_hwcb ();
744     
745     	release_write_hwcb ();
746     
747     	hwc_data.flags &= ~HWC_FLUSH;
748     }
749     
750     static int 
751     write_event_data_2 (u32 ext_int_param)
752     {
753     	write_hwcb_t *hwcb;
754     	int retval = 0;
755     
756     #ifdef DUMP_HWC_WRITE_ERROR
757     	if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
758     	    != (unsigned long) hwc_data.current_hwcb) {
759     		internal_print (
760     				       DELAYED_WRITE,
761     				       HWC_RW_PRINT_HEADER
762     				       "write_event_data_2 : "
763     				       "HWCB address does not fit "
764     				       "(expected: 0x%lx, got: 0x%lx).\n",
765     				       (unsigned long) hwc_data.current_hwcb,
766     				       ext_int_param);
767     		return -EINVAL;
768     	}
769     #endif
770     
771     	hwcb = (write_hwcb_t *) OUT_HWCB;
772     
773     #ifdef DUMP_HWC_WRITE_LIST_ERROR
774     	if (((unsigned char *) hwcb) != hwc_data.current_hwcb) {
775     		__asm__ ("LHI 1,0xe22\n\t"
776     			 "LRA 2,0(%0)\n\t"
777     			 "LRA 3,0(%1)\n\t"
778     			 "LRA 4,0(%2)\n\t"
779     			 "LRA 5,0(%3)\n\t"
780     			 "J .+0 \n\t"
781     	      :
782     	      :	 "a" (OUT_HWCB),
783     			 "a" (hwc_data.current_hwcb),
784     			 "a" (BUF_HWCB),
785     			 "a" (hwcb)
786     	      :	 "1", "2", "3", "4", "5");
787     	}
788     #endif
789     
790     #ifdef DUMP_HWC_WRITE_ERROR
791     	if (hwcb->response_code != 0x0020) {
792     		__asm__ ("LHI 1,0xe21\n\t"
793     			 "LRA 2,0(%0)\n\t"
794     			 "LRA 3,0(%1)\n\t"
795     			 "LRA 4,0(%2)\n\t"
796     			 "LH 5,0(%3)\n\t"
797     			 "SRL 5,8\n\t"
798     			 "J .+0 \n\t"
799     	      :
800     	      :	 "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
801     			 "a" (BUF_HWCB),
802     			 "a" (&(hwc_data.hwcb_count))
803     	      :	 "1", "2", "3", "4", "5");
804     	}
805     #endif
806     
807     	switch (hwcb->response_code) {
808     	case 0x0020:
809     
810     		retval = OUT_HWCB_CHAR;
811     		release_write_hwcb ();
812     		break;
813     	case 0x0040:
814     	case 0x0340:
815     	case 0x40F0:
816     		if (!hwc_data.read_statechange) {
817     			hwcb->response_code = 0;
818     			start_poll_hwc ();
819     		}
820     		retval = -EIO;
821     		break;
822     	default:
823     		internal_print (
824     				       DELAYED_WRITE,
825     				       HWC_RW_PRINT_HEADER
826     				       "write_event_data_2 : "
827     				       "failed operation "
828     				       "(response code: 0x%x "
829     				       "HWCB address: 0x%x).\n",
830     				       hwcb->response_code,
831     				       hwcb);
832     		retval = -EIO;
833     	}
834     
835     	if (retval == -EIO) {
836     
837     		hwcb->control_mask[0] = 0;
838     		hwcb->control_mask[1] = 0;
839     		hwcb->control_mask[2] = 0;
840     		hwcb->response_code = 0;
841     	}
842     	hwc_data.current_servc = 0;
843     	hwc_data.current_hwcb = NULL;
844     
845     	if (hwc_data.flags & HWC_FLUSH)
846     		flush_hwcbs ();
847     
848     	return retval;
849     }
850     
851     static void 
852     do_put_line (
853     		    unsigned char *message,
854     		    unsigned short count)
855     {
856     
857     	if (add_mto (message, count) != count) {
858     
859     		if (allocate_write_hwcb () < 0)
860     			reuse_write_hwcb ();
861     
862     #ifdef DUMP_HWC_WRITE_LIST_ERROR
863     		if (add_mto (message, count) != count)
864     			__asm__ ("LHI 1,0xe32\n\t"
865     				 "LRA 2,0(%0)\n\t"
866     				 "L 3,0(%1)\n\t"
867     				 "LRA 4,0(%2)\n\t"
868     				 "LRA 5,0(%3)\n\t"
869     				 "J .+0 \n\t"
870     		      :
871     		      :	 "a" (message), "a" (&hwc_data.kmem_pages),
872     				 "a" (BUF_HWCB), "a" (OUT_HWCB)
873     		      :	 "1", "2", "3", "4", "5");
874     #else
875     		add_mto (message, count);
876     #endif
877     	}
878     }
879     
880     static void 
881     put_line (
882     		 unsigned char *message,
883     		 unsigned short count)
884     {
885     
886     	if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_WTIMER_RUNS)) {
887     		del_timer (&hwc_data.write_timer);
888     		hwc_data.flags &= ~HWC_WTIMER_RUNS;
889     	}
890     	hwc_data.obuf_start += count;
891     
892     	do_put_line (message, count);
893     
894     	hwc_data.obuf_start -= count;
895     }
896     
897     static void 
898     set_alarm (void)
899     {
900     	write_hwcb_t *hwcb;
901     
902     	if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb))
903     		allocate_write_hwcb ();
904     
905     	hwcb = (write_hwcb_t *) BUF_HWCB;
906     	hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm;
907     }
908     
909     static void 
910     hwc_write_timeout (unsigned long data)
911     {
912     	unsigned long flags;
913     
914     	spin_lock_irqsave (&hwc_data.lock, flags);
915     
916     	hwc_data.obuf_start = hwc_data.obuf_count;
917     	if (hwc_data.obuf_count)
918     		put_line (hwc_data.obuf, hwc_data.obuf_count);
919     	hwc_data.obuf_start = 0;
920     
921     	hwc_data.obuf_cursor = 0;
922     	hwc_data.obuf_count = 0;
923     
924     	write_event_data_1 ();
925     
926     	spin_unlock_irqrestore (&hwc_data.lock, flags);
927     }
928     
929     static int 
930     do_hwc_write (
931     		     int from_user,
932     		     unsigned char *msg,
933     		     unsigned int count,
934     		     unsigned char write_time)
935     {
936     	unsigned int i_msg = 0;
937     	unsigned short int spaces = 0;
938     	unsigned int processed_characters = 0;
939     	unsigned char ch;
940     	unsigned short int obuf_count;
941     	unsigned short int obuf_cursor;
942     	unsigned short int obuf_columns;
943     
944     	if (hwc_data.obuf_start) {
945     		obuf_cursor = 0;
946     		obuf_count = 0;
947     		obuf_columns = MIN (hwc_data.ioctls.columns,
948     				    MAX_MESSAGE_SIZE - hwc_data.obuf_start);
949     	} else {
950     		obuf_cursor = hwc_data.obuf_cursor;
951     		obuf_count = hwc_data.obuf_count;
952     		obuf_columns = hwc_data.ioctls.columns;
953     	}
954     
955     	for (i_msg = 0; i_msg < count; i_msg++) {
956     		if (from_user)
957     			get_user (ch, msg + i_msg);
958     		else
959     			ch = msg[i_msg];
960     
961     		processed_characters++;
962     
963     		if ((obuf_cursor == obuf_columns) &&
964     
965     		    (ch != '\n') &&
966     
967     		    (ch != '\t')) {
968     			put_line (&hwc_data.obuf[hwc_data.obuf_start],
969     				  obuf_columns);
970     			obuf_cursor = 0;
971     			obuf_count = 0;
972     		}
973     		switch (ch) {
974     
975     		case '\n':
976     
977     			put_line (&hwc_data.obuf[hwc_data.obuf_start],
978     				  obuf_count);
979     			obuf_cursor = 0;
980     			obuf_count = 0;
981     			break;
982     
983     		case '\a':
984     
985     			hwc_data.obuf_start += obuf_count;
986     			set_alarm ();
987     			hwc_data.obuf_start -= obuf_count;
988     
989     			break;
990     
991     		case '\t':
992     
993     			do {
994     				if (obuf_cursor < obuf_columns) {
995     					hwc_data.obuf[hwc_data.obuf_start +
996     						      obuf_cursor]
997     					    = HWC_ASCEBC (' ');
998     					obuf_cursor++;
999     				} else
1000     					break;
1001     			} while (obuf_cursor % hwc_data.ioctls.width_htab);
1002     
1003     			break;
1004     
1005     		case '\f':
1006     		case '\v':
1007     
1008     			spaces = obuf_cursor;
1009     			put_line (&hwc_data.obuf[hwc_data.obuf_start],
1010     				  obuf_count);
1011     			obuf_count = obuf_cursor;
1012     			while (spaces) {
1013     				hwc_data.obuf[hwc_data.obuf_start +
1014     					      obuf_cursor - spaces]
1015     				    = HWC_ASCEBC (' ');
1016     				spaces--;
1017     			}
1018     
1019     			break;
1020     
1021     		case '\b':
1022     
1023     			if (obuf_cursor)
1024     				obuf_cursor--;
1025     			break;
1026     
1027     		case '\r':
1028     
1029     			obuf_cursor = 0;
1030     			break;
1031     
1032     		case 0x00:
1033     
1034     			put_line (&hwc_data.obuf[hwc_data.obuf_start],
1035     				  obuf_count);
1036     			obuf_cursor = 0;
1037     			obuf_count = 0;
1038     			goto out;
1039     
1040     		default:
1041     
1042     			if (isprint (ch))
1043     				hwc_data.obuf[hwc_data.obuf_start +
1044     					      obuf_cursor++]
1045     				    = HWC_ASCEBC (ch);
1046     		}
1047     		if (obuf_cursor > obuf_count)
1048     			obuf_count = obuf_cursor;
1049     	}
1050     
1051     	if (obuf_cursor) {
1052     
1053     		if (hwc_data.obuf_start ||
1054     		    (hwc_data.ioctls.final_nl == 0)) {
1055     
1056     			put_line (&hwc_data.obuf[hwc_data.obuf_start],
1057     				  obuf_count);
1058     			obuf_cursor = 0;
1059     			obuf_count = 0;
1060     		} else {
1061     
1062     			if (hwc_data.ioctls.final_nl > 0) {
1063     
1064     				if (hwc_data.flags & HWC_WTIMER_RUNS) {
1065     
1066     					mod_timer (&hwc_data.write_timer,
1067     						   jiffies + hwc_data.ioctls.final_nl * HZ / 10);
1068     				} else {
1069     
1070     					init_timer (&hwc_data.write_timer);
1071     					hwc_data.write_timer.function =
1072     					    hwc_write_timeout;
1073     					hwc_data.write_timer.data =
1074     					    (unsigned long) NULL;
1075     					hwc_data.write_timer.expires =
1076     					    jiffies +
1077     					    hwc_data.ioctls.final_nl * HZ / 10;
1078     					add_timer (&hwc_data.write_timer);
1079     					hwc_data.flags |= HWC_WTIMER_RUNS;
1080     				}
1081     			} else;
1082     
1083     		}
1084     	} else;
1085     
1086           out:
1087     
1088     	if (!hwc_data.obuf_start) {
1089     		hwc_data.obuf_cursor = obuf_cursor;
1090     		hwc_data.obuf_count = obuf_count;
1091     	}
1092     	if (write_time == IMMEDIATE_WRITE)
1093     		write_event_data_1 ();
1094     
1095     	return processed_characters;
1096     }
1097     
1098     signed int 
1099     hwc_write (int from_user, const unsigned char *msg, unsigned int count)
1100     {
1101     	unsigned long flags;
1102     	int retval;
1103     
1104     	spin_lock_irqsave (&hwc_data.lock, flags);
1105     
1106     	retval = do_hwc_write (from_user, (unsigned char *) msg,
1107     			       count, IMMEDIATE_WRITE);
1108     
1109     	spin_unlock_irqrestore (&hwc_data.lock, flags);
1110     
1111     	return retval;
1112     }
1113     
1114     unsigned int 
1115     hwc_chars_in_buffer (unsigned char flag)
1116     {
1117     	unsigned short int number = 0;
1118     	unsigned long flags;
1119     
1120     	spin_lock_irqsave (&hwc_data.lock, flags);
1121     
1122     	if (flag & IN_HWCB)
1123     		number += ALL_HWCB_CHAR;
1124     
1125     	if (flag & IN_WRITE_BUF)
1126     		number += hwc_data.obuf_cursor;
1127     
1128     	spin_unlock_irqrestore (&hwc_data.lock, flags);
1129     
1130     	return number;
1131     }
1132     
1133     static inline int 
1134     nr_setbits (kmem_pages_t arg)
1135     {
1136     	int i;
1137     	int nr = 0;
1138     
1139     	for (i = 0; i < (sizeof (arg) << 3); i++) {
1140     		if (arg & 1)
1141     			nr++;
1142     		arg >>= 1;
1143     	}
1144     
1145     	return nr;
1146     }
1147     
1148     unsigned int 
1149     hwc_write_room (unsigned char flag)
1150     {
1151     	unsigned int number = 0;
1152     	unsigned long flags;
1153     	write_hwcb_t *hwcb;
1154     
1155     	spin_lock_irqsave (&hwc_data.lock, flags);
1156     
1157     	if (flag & IN_HWCB) {
1158     
1159     		if (BUF_HWCB) {
1160     			hwcb = (write_hwcb_t *) BUF_HWCB;
1161     			number += MAX_HWCB_ROOM - hwcb->length;
1162     		}
1163     		number += (hwc_data.ioctls.kmem_hwcb -
1164     			   nr_setbits (hwc_data.kmem_pages)) *
1165     		    (MAX_HWCB_ROOM -
1166     		     (sizeof (write_hwcb_t) + sizeof (mto_t)));
1167     	}
1168     	if (flag & IN_WRITE_BUF)
1169     		number += MAX_HWCB_ROOM - hwc_data.obuf_cursor;
1170     
1171     	spin_unlock_irqrestore (&hwc_data.lock, flags);
1172     
1173     	return number;
1174     }
1175     
1176     void 
1177     hwc_flush_buffer (unsigned char flag)
1178     {
1179     	unsigned long flags;
1180     
1181     	spin_lock_irqsave (&hwc_data.lock, flags);
1182     
1183     	if (flag & IN_HWCB) {
1184     		if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
1185     			flush_hwcbs ();
1186     		else
1187     			hwc_data.flags |= HWC_FLUSH;
1188     	}
1189     	if (flag & IN_WRITE_BUF) {
1190     		hwc_data.obuf_cursor = 0;
1191     		hwc_data.obuf_count = 0;
1192     	}
1193     	spin_unlock_irqrestore (&hwc_data.lock, flags);
1194     }
1195     
1196     unsigned short int 
1197     seperate_cases (unsigned char *buf, unsigned short int count)
1198     {
1199     
1200     	unsigned short int i_in;
1201     
1202     	unsigned short int i_out = 0;
1203     
1204     	unsigned char _case = 0;
1205     
1206     	for (i_in = 0; i_in < count; i_in++) {
1207     
1208     		if (buf[i_in] == hwc_data.ioctls.delim) {
1209     
1210     			if ((i_in + 1 < count) &&
1211     			    (buf[i_in + 1] == hwc_data.ioctls.delim)) {
1212     
1213     				buf[i_out] = hwc_data.ioctls.delim;
1214     
1215     				i_out++;
1216     
1217     				i_in++;
1218     
1219     			} else
1220     				_case = ~_case;
1221     
1222     		} else {
1223     
1224     			if (_case) {
1225     
1226     				if (hwc_data.ioctls.tolower)
1227     					buf[i_out] = _ebc_toupper[buf[i_in]];
1228     
1229     				else
1230     					buf[i_out] = _ebc_tolower[buf[i_in]];
1231     
1232     			} else
1233     				buf[i_out] = buf[i_in];
1234     
1235     			i_out++;
1236     		}
1237     	}
1238     
1239     	return i_out;
1240     }
1241     
1242     #ifdef DUMP_HWCB_INPUT
1243     
1244     static int 
1245     gds_vector_name (u16 id, unsigned char name[])
1246     {
1247     	int retval = 0;
1248     
1249     	switch (id) {
1250     	case GDS_ID_MDSMU:
1251     		name = "Multiple Domain Support Message Unit";
1252     		break;
1253     	case GDS_ID_MDSRouteInfo:
1254     		name = "MDS Routing Information";
1255     		break;
1256     	case GDS_ID_AgUnWrkCorr:
1257     		name = "Agent Unit of Work Correlator";
1258     		break;
1259     	case GDS_ID_SNACondReport:
1260     		name = "SNA Condition Report";
1261     		break;
1262     	case GDS_ID_CPMSU:
1263     		name = "CP Management Services Unit";
1264     		break;
1265     	case GDS_ID_RoutTargInstr:
1266     		name = "Routing and Targeting Instructions";
1267     		break;
1268     	case GDS_ID_OpReq:
1269     		name = "Operate Request";
1270     		break;
1271     	case GDS_ID_TextCmd:
1272     		name = "Text Command";
1273     		break;
1274     
1275     	default:
1276     		name = "unknown GDS variable";
1277     		retval = -EINVAL;
1278     	}
1279     
1280     	return retval;
1281     }
1282     #endif
1283     
1284     inline static gds_vector_t *
1285     find_gds_vector (
1286     			gds_vector_t * start, void *end, u16 id)
1287     {
1288     	gds_vector_t *vec;
1289     	gds_vector_t *retval = NULL;
1290     
1291     	vec = start;
1292     
1293     	while (((void *) vec) < end) {
1294     		if (vec->gds_id == id) {
1295     
1296     #ifdef DUMP_HWCB_INPUT
1297     			int retval_name;
1298     			unsigned char name[64];
1299     
1300     			retval_name = gds_vector_name (id, name);
1301     			internal_print (
1302     					       DELAYED_WRITE,
1303     					       HWC_RW_PRINT_HEADER
1304     					  "%s at 0x%x up to 0x%x, length: %d",
1305     					       name,
1306     					       (unsigned long) vec,
1307     				      ((unsigned long) vec) + vec->length - 1,
1308     					       vec->length);
1309     			if (retval_name < 0)
1310     				internal_print (
1311     						       IMMEDIATE_WRITE,
1312     						       ", id: 0x%x\n",
1313     						       vec->gds_id);
1314     			else
1315     				internal_print (
1316     						       IMMEDIATE_WRITE,
1317     						       "\n");
1318     #endif
1319     
1320     			retval = vec;
1321     			break;
1322     		}
1323     		vec = (gds_vector_t *) (((unsigned long) vec) + vec->length);
1324     	}
1325     
1326     	return retval;
1327     }
1328     
1329     inline static gds_subvector_t *
1330     find_gds_subvector (
1331     			   gds_subvector_t * start, void *end, u8 key)
1332     {
1333     	gds_subvector_t *subvec;
1334     	gds_subvector_t *retval = NULL;
1335     
1336     	subvec = start;
1337     
1338     	while (((void *) subvec) < end) {
1339     		if (subvec->key == key) {
1340     			retval = subvec;
1341     			break;
1342     		}
1343     		subvec = (gds_subvector_t *)
1344     		    (((unsigned long) subvec) + subvec->length);
1345     	}
1346     
1347     	return retval;
1348     }
1349     
1350     inline static int 
1351     get_input (void *start, void *end)
1352     {
1353     	int count;
1354     
1355     	count = ((unsigned long) end) - ((unsigned long) start);
1356     
1357     	if (hwc_data.ioctls.tolower)
1358     		EBC_TOLOWER (start, count);
1359     
1360     	if (hwc_data.ioctls.delim)
1361     		count = seperate_cases (start, count);
1362     
1363     	HWC_EBCASC_STR (start, count);
1364     
1365     	if (hwc_data.ioctls.echo)
1366     		do_hwc_write (0, start, count, IMMEDIATE_WRITE);
1367     
1368     	if (hwc_data.calls != NULL)
1369     		if (hwc_data.calls->move_input != NULL)
1370     			(hwc_data.calls->move_input) (start, count);
1371     
1372     	return count;
1373     }
1374     
1375     inline static int 
1376     eval_selfdeftextmsg (gds_subvector_t * start, void *end)
1377     {
1378     	gds_subvector_t *subvec;
1379     	void *subvec_data;
1380     	void *subvec_end;
1381     	int retval = 0;
1382     
1383     	subvec = start;
1384     
1385     	while (((void *) subvec) < end) {
1386     		subvec = find_gds_subvector (subvec, end, 0x30);
1387     		if (!subvec)
1388     			break;
1389     		subvec_data = (void *)
1390     		    (((unsigned long) subvec) +
1391     		     sizeof (gds_subvector_t));
1392     		subvec_end = (void *)
1393     		    (((unsigned long) subvec) + subvec->length);
1394     		retval += get_input (subvec_data, subvec_end);
1395     		subvec = (gds_subvector_t *) subvec_end;
1396     	}
1397     
1398     	return retval;
1399     }
1400     
1401     inline static int 
1402     eval_textcmd (gds_subvector_t * start, void *end)
1403     {
1404     	gds_subvector_t *subvec;
1405     	gds_subvector_t *subvec_data;
1406     	void *subvec_end;
1407     	int retval = 0;
1408     
1409     	subvec = start;
1410     
1411     	while (((void *) subvec) < end) {
1412     		subvec = find_gds_subvector (
1413     					 subvec, end, GDS_KEY_SelfDefTextMsg);
1414     		if (!subvec)
1415     			break;
1416     		subvec_data = (gds_subvector_t *)
1417     		    (((unsigned long) subvec) +
1418     		     sizeof (gds_subvector_t));
1419     		subvec_end = (void *)
1420     		    (((unsigned long) subvec) + subvec->length);
1421     		retval += eval_selfdeftextmsg (subvec_data, subvec_end);
1422     		subvec = (gds_subvector_t *) subvec_end;
1423     	}
1424     
1425     	return retval;
1426     }
1427     
1428     inline static int 
1429     eval_cpmsu (gds_vector_t * start, void *end)
1430     {
1431     	gds_vector_t *vec;
1432     	gds_subvector_t *vec_data;
1433     	void *vec_end;
1434     	int retval = 0;
1435     
1436     	vec = start;
1437     
1438     	while (((void *) vec) < end) {
1439     		vec = find_gds_vector (vec, end, GDS_ID_TextCmd);
1440     		if (!vec)
1441     			break;
1442     		vec_data = (gds_subvector_t *)
1443     		    (((unsigned long) vec) + sizeof (gds_vector_t));
1444     		vec_end = (void *) (((unsigned long) vec) + vec->length);
1445     		retval += eval_textcmd (vec_data, vec_end);
1446     		vec = (gds_vector_t *) vec_end;
1447     	}
1448     
1449     	return retval;
1450     }
1451     
1452     inline static int 
1453     eval_mdsmu (gds_vector_t * start, void *end)
1454     {
1455     	gds_vector_t *vec;
1456     	gds_vector_t *vec_data;
1457     	void *vec_end;
1458     	int retval = 0;
1459     
1460     	vec = find_gds_vector (start, end, GDS_ID_CPMSU);
1461     	if (vec) {
1462     		vec_data = (gds_vector_t *)
1463     		    (((unsigned long) vec) + sizeof (gds_vector_t));
1464     		vec_end = (void *) (((unsigned long) vec) + vec->length);
1465     		retval = eval_cpmsu (vec_data, vec_end);
1466     	}
1467     	return retval;
1468     }
1469     
1470     static int 
1471     eval_evbuf (gds_vector_t * start, void *end)
1472     {
1473     	gds_vector_t *vec;
1474     	gds_vector_t *vec_data;
1475     	void *vec_end;
1476     	int retval = 0;
1477     
1478     	vec = find_gds_vector (start, end, GDS_ID_MDSMU);
1479     	if (vec) {
1480     		vec_data = (gds_vector_t *)
1481     		    (((unsigned long) vec) + sizeof (gds_vector_t));
1482     		vec_end = (void *) (((unsigned long) vec) + vec->length);
1483     		retval = eval_mdsmu (vec_data, vec_end);
1484     	}
1485     	return retval;
1486     }
1487     
1488     static inline int 
1489     eval_hwc_receive_mask (_hwcb_mask_t mask)
1490     {
1491     
1492     	hwc_data.write_nonprio
1493     	    = ((mask & ET_Msg_Mask) == ET_Msg_Mask);
1494     
1495     	hwc_data.write_prio
1496     	    = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
1497     
1498     	if (hwc_data.write_prio || hwc_data.write_nonprio) {
1499     		internal_print (
1500     				       DELAYED_WRITE,
1501     				       HWC_RW_PRINT_HEADER
1502     				       "can write messages\n");
1503     		return 0;
1504     	} else {
1505     		internal_print (
1506     				       DELAYED_WRITE,
1507     				       HWC_RW_PRINT_HEADER
1508     				       "can not write messages\n");
1509     		return -1;
1510     	}
1511     }
1512     
1513     static inline int 
1514     eval_hwc_send_mask (_hwcb_mask_t mask)
1515     {
1516     
1517     	hwc_data.read_statechange
1518     	    = ((mask & ET_StateChange_Mask) == ET_StateChange_Mask);
1519     	if (hwc_data.read_statechange)
1520     		internal_print (
1521     				       DELAYED_WRITE,
1522     				       HWC_RW_PRINT_HEADER
1523     				     "can read state change notifications\n");
1524     	else
1525     		internal_print (
1526     				       DELAYED_WRITE,
1527     				       HWC_RW_PRINT_HEADER
1528     				 "can not read state change notifications\n");
1529     
1530     	hwc_data.read_nonprio
1531     	    = ((mask & ET_OpCmd_Mask) == ET_OpCmd_Mask);
1532     	if (hwc_data.read_nonprio)
1533     		internal_print (
1534     				       DELAYED_WRITE,
1535     				       HWC_RW_PRINT_HEADER
1536     				       "can read commands\n");
1537     
1538     	hwc_data.read_prio
1539     	    = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
1540     	if (hwc_data.read_prio)
1541     		internal_print (
1542     				       DELAYED_WRITE,
1543     				       HWC_RW_PRINT_HEADER
1544     				       "can read priority commands\n");
1545     
1546     	if (hwc_data.read_prio || hwc_data.read_nonprio) {
1547     		return 0;
1548     	} else {
1549     		internal_print (
1550     				       DELAYED_WRITE,
1551     				       HWC_RW_PRINT_HEADER
1552     				     "can not read commands from operator\n");
1553     		return -1;
1554     	}
1555     }
1556     
1557     static int 
1558     eval_statechangebuf (statechangebuf_t * scbuf)
1559     {
1560     	int retval = 0;
1561     
1562     	internal_print (
1563     			       DELAYED_WRITE,
1564     			       HWC_RW_PRINT_HEADER
1565     			       "HWC state change detected\n");
1566     
1567     	if (scbuf->validity_hwc_active_facility_mask) {
1568     
1569     	}
1570     	if (scbuf->validity_hwc_receive_mask) {
1571     
1572     		if (scbuf->mask_length != 4) {
1573     #ifdef DUMP_HWC_INIT_ERROR
1574     			__asm__ ("LHI 1,0xe50\n\t"
1575     				 "LRA 2,0(%0)\n\t"
1576     				 "J .+0 \n\t"
1577     		      :
1578     		      :	 "a" (scbuf)
1579     		      :	 "1", "2");
1580     #endif
1581     		} else {
1582     
1583     			retval += eval_hwc_receive_mask
1584     			    (scbuf->hwc_receive_mask);
1585     		}
1586     	}
1587     	if (scbuf->validity_hwc_send_mask) {
1588     
1589     		if (scbuf->mask_length != 4) {
1590     #ifdef DUMP_HWC_INIT_ERROR
1591     			__asm__ ("LHI 1,0xe51\n\t"
1592     				 "LRA 2,0(%0)\n\t"
1593     				 "J .+0 \n\t"
1594     		      :
1595     		      :	 "a" (scbuf)
1596     		      :	 "1", "2");
1597     #endif
1598     		} else {
1599     
1600     			retval += eval_hwc_send_mask
1601     			    (scbuf->hwc_send_mask);
1602     		}
1603     	}
1604     	if (scbuf->validity_read_data_function_mask) {
1605     
1606     	}
1607     	return retval;
1608     }
1609     
1610     static int 
1611     process_evbufs (void *start, void *end)
1612     {
1613     	int retval = 0;
1614     	evbuf_t *evbuf;
1615     	void *evbuf_end;
1616     	gds_vector_t *evbuf_data;
1617     
1618     	evbuf = (evbuf_t *) start;
1619     	while (((void *) evbuf) < end) {
1620     		evbuf_data = (gds_vector_t *)
1621     		    (((unsigned long) evbuf) + sizeof (evbuf_t));
1622     		evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length);
1623     		switch (evbuf->type) {
1624     		case ET_OpCmd:
1625     		case ET_CntlProgOpCmd:
1626     		case ET_PMsgCmd:
1627     #ifdef DUMP_HWCB_INPUT
1628     
1629     			internal_print (
1630     					       DELAYED_WRITE,
1631     					       HWC_RW_PRINT_HEADER
1632     					       "event buffer "
1633     					   "at 0x%x up to 0x%x, length: %d\n",
1634     					       (unsigned long) evbuf,
1635     					       (unsigned long) (evbuf_end - 1),
1636     					       evbuf->length);
1637     			dump_storage_area ((void *) evbuf, evbuf->length);
1638     #endif
1639     			retval += eval_evbuf (evbuf_data, evbuf_end);
1640     			break;
1641     		case ET_StateChange:
1642     			retval += eval_statechangebuf
1643     			    ((statechangebuf_t *) evbuf);
1644     			break;
1645     		default:
1646     			internal_print (
1647     					       DELAYED_WRITE,
1648     					       HWC_RW_PRINT_HEADER
1649     					       "unconditional read: "
1650     					       "unknown event buffer found, "
1651     					       "type 0x%x",
1652     					       evbuf->type);
1653     			retval = -ENOSYS;
1654     		}
1655     		evbuf = (evbuf_t *) evbuf_end;
1656     	}
1657     	return retval;
1658     }
1659     
1660     static int 
1661     unconditional_read_1 (void)
1662     {
1663     	unsigned short int condition_code;
1664     	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
1665     	int retval;
1666     
1667     #if 0
1668     
1669     	if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio))
1670     		return -EOPNOTSUPP;
1671     
1672     	if (hwc_data.current_servc)
1673     		return -EBUSY;
1674     #endif
1675     
1676     	memset (hwcb, 0x00, PAGE_SIZE);
1677     	memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t));
1678     
1679     	condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page);
1680     
1681     #ifdef DUMP_HWC_READ_ERROR
1682     	if (condition_code == HWC_NOT_OPERATIONAL)
1683     		__asm__ ("LHI 1,0xe40\n\t"
1684     			 "L 2,0(%0)\n\t"
1685     			 "LRA 3,0(%1)\n\t"
1686     			 "J .+0 \n\t"
1687     	      :
1688     	      :	 "a" (&condition_code), "a" (hwc_data.page)
1689     	      :	 "1", "2", "3");
1690     #endif
1691     
1692     	switch (condition_code) {
1693     	case HWC_COMMAND_INITIATED:
1694     		hwc_data.current_servc = HWC_CMDW_READDATA;
1695     		hwc_data.current_hwcb = hwc_data.page;
1696     		retval = condition_code;
1697     		break;
1698     	case HWC_BUSY:
1699     		retval = -EBUSY;
1700     		break;
1701     	default:
1702     		retval = -EIO;
1703     	}
1704     
1705     	return retval;
1706     }
1707     
1708     static int 
1709     unconditional_read_2 (u32 ext_int_param)
1710     {
1711     	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
1712     
1713     #ifdef DUMP_HWC_READ_ERROR
1714     	if ((hwcb->response_code != 0x0020) &&
1715     	    (hwcb->response_code != 0x0220) &&
1716     	    (hwcb->response_code != 0x60F0) &&
1717     	    (hwcb->response_code != 0x62F0))
1718     		__asm__ ("LHI 1,0xe41\n\t"
1719     			 "LRA 2,0(%0)\n\t"
1720     			 "L 3,0(%1)\n\t"
1721     			 "J .+0\n\t"
1722     	      :
1723     	      :	 "a" (hwc_data.page), "a" (&(hwcb->response_code))
1724     	      :	 "1", "2", "3");
1725     #endif
1726     
1727     	hwc_data.current_servc = 0;
1728     	hwc_data.current_hwcb = NULL;
1729     
1730     	switch (hwcb->response_code) {
1731     
1732     	case 0x0020:
1733     	case 0x0220:
1734     		return process_evbufs (
1735     		     (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)),
1736     			    (void *) (((unsigned long) hwcb) + hwcb->length));
1737     
1738     	case 0x60F0:
1739     	case 0x62F0:
1740     		internal_print (
1741     				       IMMEDIATE_WRITE,
1742     				       HWC_RW_PRINT_HEADER
1743     				       "unconditional read: "
1744     				     "got interrupt and tried to read input, "
1745     				  "but nothing found (response code=0x%x).\n",
1746     				       hwcb->response_code);
1747     		return 0;
1748     
1749     	case 0x0100:
1750     		internal_print (
1751     				       IMMEDIATE_WRITE,
1752     				       HWC_RW_PRINT_HEADER
1753     			 "unconditional read: HWCB boundary violation - this "
1754     			 "must not occur in a correct driver, please contact "
1755     				       "author\n");
1756     		return -EIO;
1757     
1758     	case 0x0300:
1759     		internal_print (
1760     				       IMMEDIATE_WRITE,
1761     				       HWC_RW_PRINT_HEADER
1762     				       "unconditional read: "
1763     			"insufficient HWCB length - this must not occur in a "
1764     				   "correct driver, please contact author\n");
1765     		return -EIO;
1766     
1767     	case 0x01F0:
1768     		internal_print (
1769     				       IMMEDIATE_WRITE,
1770     				       HWC_RW_PRINT_HEADER
1771     				       "unconditional read: "
1772     			 "invalid command - this must not occur in a correct "
1773     				       "driver, please contact author\n");
1774     		return -EIO;
1775     
1776     	case 0x40F0:
1777     		internal_print (
1778     				       IMMEDIATE_WRITE,
1779     				       HWC_RW_PRINT_HEADER
1780     			       "unconditional read: invalid function code\n");
1781     		return -EIO;
1782     
1783     	case 0x70F0:
1784     		internal_print (
1785     				       IMMEDIATE_WRITE,
1786     				       HWC_RW_PRINT_HEADER
1787     			      "unconditional read: invalid selection mask\n");
1788     		return -EIO;
1789     
1790     	case 0x0040:
1791     		internal_print (
1792     				       IMMEDIATE_WRITE,
1793     				       HWC_RW_PRINT_HEADER
1794     				 "unconditional read: HWC equipment check\n");
1795     		return -EIO;
1796     
1797     	default:
1798     		internal_print (
1799     				       IMMEDIATE_WRITE,
1800     				       HWC_RW_PRINT_HEADER
1801     			"unconditional read: invalid response code %x - this "
1802     			 "must not occur in a correct driver, please contact "
1803     				       "author\n",
1804     				       hwcb->response_code);
1805     		return -EIO;
1806     	}
1807     }
1808     
1809     static int 
1810     write_event_mask_1 (void)
1811     {
1812     	unsigned int condition_code;
1813     	int retval;
1814     
1815     	condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);
1816     
1817     #ifdef DUMP_HWC_INIT_ERROR
1818     
1819     	if (condition_code == HWC_NOT_OPERATIONAL)
1820     		__asm__ ("LHI 1,0xe10\n\t"
1821     			 "L 2,0(%0)\n\t"
1822     			 "LRA 3,0(%1)\n\t"
1823     			 "J .+0\n\t"
1824     	      :
1825     	      :	 "a" (&condition_code), "a" (hwc_data.page)
1826     	      :	 "1", "2", "3");
1827     #endif
1828     
1829     	switch (condition_code) {
1830     	case HWC_COMMAND_INITIATED:
1831     		hwc_data.current_servc = HWC_CMDW_WRITEMASK;
1832     		hwc_data.current_hwcb = hwc_data.page;
1833     		retval = condition_code;
1834     		break;
1835     	case HWC_BUSY:
1836     		retval = -EBUSY;
1837     		break;
1838     	default:
1839     		retval = -EIO;
1840     	}
1841     
1842     	return retval;
1843     }
1844     
1845     static int 
1846     write_event_mask_2 (u32 ext_int_param)
1847     {
1848     	init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;
1849     	int retval = 0;
1850     
1851     	if (hwcb->response_code != 0x0020) {
1852     #ifdef DUMP_HWC_INIT_ERROR
1853     		__asm__ ("LHI 1,0xe11\n\t"
1854     			 "LRA 2,0(%0)\n\t"
1855     			 "L 3,0(%1)\n\t"
1856     			 "J .+0\n\t"
1857     	      :
1858     	      :	 "a" (hwcb), "a" (&(hwcb->response_code))
1859     	      :	 "1", "2", "3");
1860     #else
1861     		retval = -1;
1862     #endif
1863     	} else {
1864     		if (hwcb->mask_length != 4) {
1865     #ifdef DUMP_HWC_INIT_ERROR
1866     			__asm__ ("LHI 1,0xe52\n\t"
1867     				 "LRA 2,0(%0)\n\t"
1868     				 "J .+0 \n\t"
1869     		      :
1870     		      :	 "a" (hwcb)
1871     		      :	 "1", "2");
1872     #endif
1873     		} else {
1874     			retval += eval_hwc_receive_mask
1875     			    (hwcb->hwc_receive_mask);
1876     			retval += eval_hwc_send_mask (hwcb->hwc_send_mask);
1877     		}
1878     	}
1879     
1880     	hwc_data.current_servc = 0;
1881     	hwc_data.current_hwcb = NULL;
1882     
1883     	return retval;
1884     }
1885     
1886     static int 
1887     set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct)
1888     {
1889     	int retval = 0;
1890     	hwc_ioctls_t tmp;
1891     
1892     	if (ioctls->width_htab > MAX_MESSAGE_SIZE) {
1893     		if (correct)
1894     			tmp.width_htab = MAX_MESSAGE_SIZE;
1895     		else
1896     			retval = -EINVAL;
1897     	} else
1898     		tmp.width_htab = ioctls->width_htab;
1899     
1900     	tmp.echo = ioctls->echo;
1901     
1902     	if (ioctls->columns > MAX_MESSAGE_SIZE) {
1903     		if (correct)
1904     			tmp.columns = MAX_MESSAGE_SIZE;
1905     		else
1906     			retval = -EINVAL;
1907     	} else
1908     		tmp.columns = ioctls->columns;
1909     
1910     	tmp.final_nl = ioctls->final_nl;
1911     
1912     	if (ioctls->max_hwcb < 2) {
1913     		if (correct)
1914     			tmp.max_hwcb = 2;
1915     		else
1916     			retval = -EINVAL;
1917     	} else
1918     		tmp.max_hwcb = ioctls->max_hwcb;
1919     
1920     	tmp.tolower = ioctls->tolower;
1921     
1922     	if (ioctls->kmem_hwcb > ioctls->max_hwcb) {
1923     		if (correct)
1924     			tmp.kmem_hwcb = ioctls->max_hwcb;
1925     		else
1926     			retval = -EINVAL;
1927     	} else
1928     		tmp.kmem_hwcb = ioctls->kmem_hwcb;
1929     
1930     	if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) {
1931     		if (correct)
1932     			ioctls->kmem_hwcb = MAX_KMEM_PAGES;
1933     		else
1934     			retval = -EINVAL;
1935     	}
1936     	if (ioctls->kmem_hwcb < 2) {
1937     		if (correct)
1938     			ioctls->kmem_hwcb = 2;
1939     		else
1940     			retval = -EINVAL;
1941     	}
1942     	tmp.delim = ioctls->delim;
1943     
1944     	if (!(retval < 0))
1945     		hwc_data.ioctls = tmp;
1946     
1947     	return retval;
1948     }
1949     
1950     int 
1951     do_hwc_init (void)
1952     {
1953     	int retval;
1954     
1955     	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
1956     
1957     	do {
1958     
1959     		retval = write_event_mask_1 ();
1960     
1961     		if (retval == -EBUSY) {
1962     
1963     			hwc_data.flags |= HWC_INIT;
1964     
1965     			__ctl_store (cr0, 0, 0);
1966     			cr0_save = cr0;
1967     			cr0 |= 0x00000200;
1968     			cr0 &= 0xFFFFF3AC;
1969     			__ctl_load (cr0, 0, 0);
1970     
1971     			asm volatile ("STOSM %0,0x01"
1972     				      :"=m" (psw_mask)::"memory");
1973     
1974     			while (!(hwc_data.flags & HWC_INTERRUPT))
1975     				barrier ();
1976     
1977     			asm volatile ("STNSM %0,0xFE"
1978     				      :"=m" (psw_mask)::"memory");
1979     
1980     			__ctl_load (cr0_save, 0, 0);
1981     
1982     			hwc_data.flags &= ~HWC_INIT;
1983     		}
1984     	} while (retval == -EBUSY);
1985     
1986     	if (retval == -EIO) {
1987     		hwc_data.flags |= HWC_BROKEN;
1988     		printk (HWC_RW_PRINT_HEADER "HWC not operational\n");
1989     	}
1990     	return retval;
1991     }
1992     
1993     void hwc_interrupt_handler (struct pt_regs *regs, __u16 code);
1994     
1995     int 
1996     hwc_init (void)
1997     {
1998     	int retval;
1999     
2000     #ifdef BUFFER_STRESS_TEST
2001     
2002     	init_hwcb_t *hwcb;
2003     	int i;
2004     
2005     #endif
2006     
2007     	if (register_external_interrupt (0x2401, hwc_interrupt_handler) != 0)
2008     		panic ("Couldn't request external interrupts 0x2401");
2009     
2010     	spin_lock_init (&hwc_data.lock);
2011     
2012     #ifdef USE_VM_DETECTION
2013     
2014     	if (MACHINE_IS_VM) {
2015     
2016     		if (hwc_data.init_ioctls.columns > 76)
2017     			hwc_data.init_ioctls.columns = 76;
2018     		hwc_data.init_ioctls.tolower = 1;
2019     		if (!hwc_data.init_ioctls.delim)
2020     			hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER;
2021     	} else {
2022     		hwc_data.init_ioctls.tolower = 0;
2023     		hwc_data.init_ioctls.delim = 0;
2024     	}
2025     #endif
2026     	retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
2027     
2028     	hwc_data.kmem_start = (unsigned long)
2029     	    alloc_bootmem_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
2030     	hwc_data.kmem_end = hwc_data.kmem_start +
2031     	    hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;
2032     
2033     	retval = do_hwc_init ();
2034     
2035     	ctl_set_bit (0, 9);
2036     
2037     #ifdef BUFFER_STRESS_TEST
2038     
2039     	internal_print (
2040     			       DELAYED_WRITE,
2041     			       HWC_RW_PRINT_HEADER
2042     			       "use %i bytes for buffering.\n",
2043     			       hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
2044     	for (i = 0; i < 500; i++) {
2045     		hwcb = (init_hwcb_t *) BUF_HWCB;
2046     		internal_print (
2047     				       DELAYED_WRITE,
2048     				       HWC_RW_PRINT_HEADER
2049     			  "This is stress test message #%i, free: %i bytes\n",
2050     				       i,
2051     			     MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t)));
2052     	}
2053     
2054     #endif
2055     
2056     	return /*retval */ 0;
2057     }
2058     
2059     signed int 
2060     hwc_register_calls (hwc_high_level_calls_t * calls)
2061     {
2062     	if (calls == NULL)
2063     		return -EINVAL;
2064     
2065     	if (hwc_data.calls != NULL)
2066     		return -EBUSY;
2067     
2068     	hwc_data.calls = calls;
2069     	return 0;
2070     }
2071     
2072     signed int 
2073     hwc_unregister_calls (hwc_high_level_calls_t * calls)
2074     {
2075     	if (hwc_data.calls == NULL)
2076     		return -EINVAL;
2077     
2078     	if (calls != hwc_data.calls)
2079     		return -EINVAL;
2080     
2081     	hwc_data.calls = NULL;
2082     	return 0;
2083     }
2084     
2085     int 
2086     hwc_send (hwc_request_t * req)
2087     {
2088     	unsigned long flags;
2089     	int retval;
2090     	int cc;
2091     
2092     	spin_lock_irqsave (&hwc_data.lock, flags);
2093     	if (!req || !req->callback || !req->block) {
2094     		retval = -EINVAL;
2095     		goto unlock;
2096     	}
2097     	if (hwc_data.request) {
2098     		retval = -ENOTSUPP;
2099     		goto unlock;
2100     	}
2101     	hwc_data.request = req;
2102     	cc = service_call (req->word, req->block);
2103     	switch (cc) {
2104     	case 0:
2105     		hwc_data.current_servc = req->word;
2106     		hwc_data.current_hwcb = req->block;
2107     		retval = 0;
2108     		break;
2109     	case 2:
2110     		retval = -EBUSY;
2111     		break;
2112     	default:
2113     		retval = -ENOSYS;
2114     
2115     	}
2116           unlock:
2117     	spin_unlock_irqrestore (&hwc_data.lock, flags);
2118     	return retval;
2119     }
2120     
2121     EXPORT_SYMBOL (hwc_send);
2122     
2123     void 
2124     do_hwc_callback (u32 ext_int_param)
2125     {
2126     	if (!hwc_data.request || !hwc_data.request->callback)
2127     		return;
2128     	if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
2129     	    != (unsigned long) hwc_data.request->block)
2130     		return;
2131     	hwc_data.request->callback (hwc_data.request);
2132     	hwc_data.request = NULL;
2133     	hwc_data.current_hwcb = NULL;
2134     	hwc_data.current_servc = 0;
2135     }
2136     
2137     void 
2138     hwc_do_interrupt (u32 ext_int_param)
2139     {
2140     	u32 finished_hwcb = ext_int_param & HWC_EXT_INT_PARAM_ADDR;
2141     	u32 evbuf_pending = ext_int_param & HWC_EXT_INT_PARAM_PEND;
2142     
2143     	if (hwc_data.flags & HWC_PTIMER_RUNS) {
2144     		del_timer (&hwc_data.poll_timer);
2145     		hwc_data.flags &= ~HWC_PTIMER_RUNS;
2146     	}
2147     	if (finished_hwcb) {
2148     
2149     		if ((unsigned long) hwc_data.current_hwcb != finished_hwcb) {
2150     			internal_print (
2151     					       DELAYED_WRITE,
2152     					       HWC_RW_PRINT_HEADER
2153     					       "interrupt: mismatch: "
2154     					       "ext. int param. (0x%x) vs. "
2155     					       "current HWCB (0x%x)\n",
2156     					       ext_int_param,
2157     					       hwc_data.current_hwcb);
2158     		} else {
2159     			if (hwc_data.request) {
2160     
2161     				do_hwc_callback (ext_int_param);
2162     			} else {
2163     
2164     				switch (hwc_data.current_servc) {
2165     
2166     				case HWC_CMDW_WRITEMASK:
2167     
2168     					write_event_mask_2 (ext_int_param);
2169     					break;
2170     
2171     				case HWC_CMDW_WRITEDATA:
2172     
2173     					write_event_data_2 (ext_int_param);
2174     					break;
2175     
2176     				case HWC_CMDW_READDATA:
2177     
2178     					unconditional_read_2 (ext_int_param);
2179     					break;
2180     				default:
2181     				}
2182     			}
2183     		}
2184     	} else {
2185     
2186     		if (hwc_data.current_hwcb) {
2187     			internal_print (
2188     					       DELAYED_WRITE,
2189     					       HWC_RW_PRINT_HEADER
2190     					       "interrupt: mismatch: "
2191     					       "ext. int. param. (0x%x) vs. "
2192     					       "current HWCB (0x%x)\n",
2193     					       ext_int_param,
2194     					       hwc_data.current_hwcb);
2195     		}
2196     	}
2197     
2198     	if (evbuf_pending) {
2199     
2200     		unconditional_read_1 ();
2201     	} else {
2202     
2203     		write_event_data_1 ();
2204     	}
2205     
2206     	if (!hwc_data.calls || !hwc_data.calls->wake_up)
2207     		return;
2208     	(hwc_data.calls->wake_up) ();
2209     }
2210     
2211     void 
2212     hwc_interrupt_handler (struct pt_regs *regs, __u16 code)
2213     {
2214     	int cpu = smp_processor_id ();
2215     
2216     	u32 ext_int_param = hwc_ext_int_param ();
2217     
2218     	irq_enter (cpu, 0x2401);
2219     
2220     	if (hwc_data.flags & HWC_INIT) {
2221     
2222     		hwc_data.flags |= HWC_INTERRUPT;
2223     	} else if (hwc_data.flags & HWC_BROKEN) {
2224     
2225     		if (!do_hwc_init ()) {
2226     			hwc_data.flags &= ~HWC_BROKEN;
2227     			internal_print (DELAYED_WRITE,
2228     					HWC_RW_PRINT_HEADER
2229     					"delayed HWC setup after"
2230     					" temporary breakdown"
2231     					" (ext. int. parameter=0x%x)\n",
2232     					ext_int_param);
2233     		}
2234     	} else {
2235     		spin_lock (&hwc_data.lock);
2236     		hwc_do_interrupt (ext_int_param);
2237     		spin_unlock (&hwc_data.lock);
2238     	}
2239     	irq_exit (cpu, 0x2401);
2240     }
2241     
2242     void 
2243     hwc_unblank (void)
2244     {
2245     
2246     	spin_lock (&hwc_data.lock);
2247     	spin_unlock (&hwc_data.lock);
2248     
2249     	__ctl_store (cr0, 0, 0);
2250     	cr0_save = cr0;
2251     	cr0 |= 0x00000200;
2252     	cr0 &= 0xFFFFF3AC;
2253     	__ctl_load (cr0, 0, 0);
2254     
2255     	asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");
2256     
2257     	while (ALL_HWCB_CHAR)
2258     		barrier ();
2259     
2260     	asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");
2261     
2262     	__ctl_load (cr0_save, 0, 0);
2263     }
2264     
2265     int 
2266     hwc_ioctl (unsigned int cmd, unsigned long arg)
2267     {
2268     	hwc_ioctls_t tmp = hwc_data.ioctls;
2269     	int retval = 0;
2270     	unsigned long flags;
2271     	unsigned int obuf;
2272     
2273     	spin_lock_irqsave (&hwc_data.lock, flags);
2274     
2275     	switch (cmd) {
2276     
2277     	case TIOCHWCSHTAB:
2278     		if (get_user (tmp.width_htab, (ioctl_htab_t *) arg))
2279     			goto fault;
2280     		break;
2281     
2282     	case TIOCHWCSECHO:
2283     		if (get_user (tmp.echo, (ioctl_echo_t *) arg))
2284     			goto fault;
2285     		break;
2286     
2287     	case TIOCHWCSCOLS:
2288     		if (get_user (tmp.columns, (ioctl_cols_t *) arg))
2289     			goto fault;
2290     		break;
2291     
2292     	case TIOCHWCSNL:
2293     		if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))
2294     			goto fault;
2295     		break;
2296     
2297     	case TIOCHWCSOBUF:
2298     		if (get_user (obuf, (unsigned int *) arg))
2299     			goto fault;
2300     		if (obuf & 0xFFF)
2301     			tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12);
2302     		else
2303     			tmp.max_hwcb = (obuf >> 12);
2304     		break;
2305     
2306     	case TIOCHWCSCASE:
2307     		if (get_user (tmp.tolower, (ioctl_case_t *) arg))
2308     			goto fault;
2309     		break;
2310     
2311     	case TIOCHWCSDELIM:
2312     		if (get_user (tmp.delim, (ioctl_delim_t *) arg))
2313     			goto fault;
2314     		break;
2315     
2316     	case TIOCHWCSINIT:
2317     		retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
2318     		break;
2319     
2320     	case TIOCHWCGHTAB:
2321     		if (put_user (tmp.width_htab, (ioctl_htab_t *) arg))
2322     			goto fault;
2323     		break;
2324     
2325     	case TIOCHWCGECHO:
2326     		if (put_user (tmp.echo, (ioctl_echo_t *) arg))
2327     			goto fault;
2328     		break;
2329     
2330     	case TIOCHWCGCOLS:
2331     		if (put_user (tmp.columns, (ioctl_cols_t *) arg))
2332     			goto fault;
2333     		break;
2334     
2335     	case TIOCHWCGNL:
2336     		if (put_user (tmp.final_nl, (ioctl_nl_t *) arg))
2337     			goto fault;
2338     		break;
2339     
2340     	case TIOCHWCGOBUF:
2341     		if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg))
2342     			goto fault;
2343     		break;
2344     
2345     	case TIOCHWCGKBUF:
2346     		if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg))
2347     			goto fault;
2348     		break;
2349     
2350     	case TIOCHWCGCASE:
2351     		if (put_user (tmp.tolower, (ioctl_case_t *) arg))
2352     			goto fault;
2353     		break;
2354     
2355     	case TIOCHWCGDELIM:
2356     		if (put_user (tmp.delim, (ioctl_delim_t *) arg))
2357     			goto fault;
2358     		break;
2359     #if 0
2360     
2361     	case TIOCHWCGINIT:
2362     		if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg))
2363     			goto fault;
2364     		break;
2365     
2366     	case TIOCHWCGCURR:
2367     		if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg))
2368     			goto fault;
2369     		break;
2370     #endif
2371     
2372     	default:
2373     		goto noioctlcmd;
2374     	}
2375     
2376     	if (_IOC_DIR (cmd) == _IOC_WRITE)
2377     		retval = set_hwc_ioctls (&tmp, 0);
2378     
2379     	goto out;
2380     
2381           fault:
2382     	retval = -EFAULT;
2383     	goto out;
2384           noioctlcmd:
2385     	retval = -ENOIOCTLCMD;
2386           out:
2387     	spin_unlock_irqrestore (&hwc_data.lock, flags);
2388     	return retval;
2389     }
2390