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