2 * drivers/s390/char/hwc_rw.c
3 * driver: reading from and writing to system console on S/390 via HWC
6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/ctype.h>
21 #include <linux/timer.h>
22 #include <linux/bootmem.h>
23 #include <linux/module.h>
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>
31 #include <asm/s390_ext.h>
35 #define MIN(a,b) (((a<b) ? a : b))
38 extern void ctrl_alt_del (void);
40 #define HWC_RW_PRINT_HEADER "hwc low level driver: "
42 #define USE_VM_DETECTION
44 #define DEFAULT_CASE_DELIMITER '%'
46 #undef DUMP_HWC_INIT_ERROR
48 #undef DUMP_HWC_WRITE_ERROR
50 #undef DUMP_HWC_WRITE_LIST_ERROR
52 #undef DUMP_HWC_READ_ERROR
54 #undef DUMP_HWCB_INPUT
56 #undef BUFFER_STRESS_TEST
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))
69 #define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t))
71 #define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t))
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
78 #define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)]))
80 #define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum)
82 #define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number)
84 #define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost)
86 #define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost)
88 #define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost)
90 #define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next)
92 #define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB)
94 #define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB)
96 #define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB)
98 #define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB)
100 #define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB)
102 #define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB)
104 #define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB)
106 #define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB)
108 #define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB)
110 #define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB)
112 #define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)
120 static unsigned char _obuf[MAX_HWCB_ROOM];
123 _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
125 typedef unsigned long kmem_pages_t;
127 #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
129 #define HWC_WTIMER_RUNS 1
133 #define HWC_INTERRUPT 16
134 #define HWC_PTIMER_RUNS 32
140 hwc_ioctls_t init_ioctls;
142 unsigned char *hwcb_list_head;
144 unsigned char *hwcb_list_tail;
146 unsigned short int mto_number;
148 unsigned int mto_char_sum;
150 unsigned char hwcb_count;
152 unsigned long kmem_start;
154 unsigned long kmem_end;
156 kmem_pages_t kmem_pages;
160 unsigned short int obuf_cursor;
162 unsigned short int obuf_count;
164 unsigned short int obuf_start;
170 unsigned char *current_hwcb;
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;
181 hwc_high_level_calls_t *calls;
183 hwc_request_t *request;
187 struct timer_list write_timer;
189 struct timer_list poll_timer;
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)));
238 static ext_int_info_t ext_int_info_hwc;
240 #define DELAYED_WRITE 0
241 #define IMMEDIATE_WRITE 1
243 static signed int do_hwc_write (int from_user, unsigned char *,
247 unsigned char hwc_ip_buf[512];
249 static asmlinkage int
250 internal_print (char write_time, char *fmt,...)
255 va_start (args, fmt);
256 i = vsprintf (hwc_ip_buf, fmt, args);
258 return do_hwc_write (0, hwc_ip_buf, i, write_time);
262 hwc_printk (const char *fmt,...)
269 spin_lock_irqsave (&hwc_data.lock, flags);
271 i = vsprintf (hwc_ip_buf, fmt, args);
273 retval = do_hwc_write (0, hwc_ip_buf, i, IMMEDIATE_WRITE);
275 spin_unlock_irqrestore (&hwc_data.lock, flags);
280 #ifdef DUMP_HWCB_INPUT
283 dump_storage_area (unsigned char *area, unsigned short int count)
285 unsigned short int index;
286 ioctl_nl_t old_final_nl;
291 old_final_nl = hwc_data.ioctls.final_nl;
292 hwc_data.ioctls.final_nl = 1;
294 internal_print (DELAYED_WRITE, "\n%8x ", area);
296 for (index = 0; index < count; index++) {
298 if (area[index] <= 0xF)
299 internal_print (DELAYED_WRITE, "0%x", area[index]);
301 internal_print (DELAYED_WRITE, "%x", area[index]);
303 if ((index & 0xF) == 0xF)
304 internal_print (DELAYED_WRITE, "\n%8x ",
306 else if ((index & 3) == 3)
307 internal_print (DELAYED_WRITE, " ");
310 internal_print (IMMEDIATE_WRITE, "\n");
312 hwc_data.ioctls.final_nl = old_final_nl;
318 u32 hwc_command_word,
319 unsigned char hwcb[])
321 unsigned int condition_code = 1;
323 __asm__ __volatile__ ("L 1, 0(%0) \n\t"
325 ".long 0xB2200012 \n\t"
327 :"a" (&hwc_command_word), "a" (hwcb)
328 :"1", "2", "memory");
330 __asm__ __volatile__ ("IPM %0 \n\t"
332 :"=r" (condition_code));
334 return condition_code;
337 static inline unsigned long
338 hwc_ext_int_param (void)
342 __asm__ __volatile__ ("L %0,128\n\t"
345 return (unsigned long) param;
349 prepare_write_hwcb (void)
359 hwcb = (write_hwcb_t *) BUF_HWCB;
361 memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t));
367 sane_write_hwcb (void)
369 unsigned short int lost_msg;
370 unsigned int lost_char;
371 unsigned char lost_hwcb;
372 unsigned char *bad_addr;
379 if ((unsigned long) OUT_HWCB & 0xFFF) {
383 #ifdef DUMP_HWC_WRITE_LIST_ERROR
384 __asm__ ("LHI 1,0xe30\n\t"
392 hwc_data.kmem_pages = 0;
393 if ((unsigned long) BUF_HWCB & 0xFFF) {
395 lost_hwcb = hwc_data.hwcb_count;
396 lost_msg = ALL_HWCB_MTO;
397 lost_char = ALL_HWCB_CHAR;
403 hwc_data.hwcb_count = 0;
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;
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;
415 if (page >= hwc_data.kmem_start &&
416 page <= hwc_data.kmem_end) {
419 ((page - hwc_data.kmem_start) >> 12);
420 set_bit (page_nr, &hwc_data.kmem_pages);
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,
434 ALL_HWCB_CHAR, ALL_HWCB_MTO);
440 reuse_write_hwcb (void)
444 if (hwc_data.hwcb_count < 2)
445 #ifdef DUMP_HWC_WRITE_LIST_ERROR
446 __asm__ ("LHI 1,0xe31\n\t"
451 : "a" (BUF_HWCB), "a" (OUT_HWCB)
457 if (hwc_data.current_hwcb == OUT_HWCB) {
459 if (hwc_data.hwcb_count > 2) {
461 BUF_HWCB_NEXT = OUT_HWCB_NEXT;
463 BUF_HWCB = OUT_HWCB_NEXT;
465 OUT_HWCB_NEXT = BUF_HWCB_NEXT;
467 BUF_HWCB_NEXT = NULL;
471 BUF_HWCB_NEXT = OUT_HWCB;
475 OUT_HWCB = OUT_HWCB_NEXT;
477 BUF_HWCB_NEXT = NULL;
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;
486 retval = prepare_write_hwcb ();
488 if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
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,
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",
510 hwc_data.hwcb_count * PAGE_SIZE,
519 allocate_write_hwcb (void)
524 if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
527 page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES);
528 if (page_nr < hwc_data.ioctls.kmem_hwcb) {
530 page = (unsigned char *)
531 (hwc_data.kmem_start + (page_nr << 12));
532 set_bit (page_nr, &hwc_data.kmem_pages);
534 page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);
542 BUF_HWCB_NEXT = page;
546 BUF_HWCB_NEXT = NULL;
548 hwc_data.hwcb_count++;
550 prepare_write_hwcb ();
552 BUF_HWCB_TIMES_LOST = 0;
553 BUF_HWCB_MTO_LOST = 0;
554 BUF_HWCB_CHAR_LOST = 0;
556 #ifdef BUFFER_STRESS_TEST
560 "*** " HWC_RW_PRINT_HEADER
561 "page #%i at 0x%x for buffering allocated. ***\n",
562 hwc_data.hwcb_count, page);
570 release_write_hwcb (void)
575 if (!hwc_data.hwcb_count)
578 if (hwc_data.hwcb_count == 1) {
580 prepare_write_hwcb ();
584 BUF_HWCB_TIMES_LOST = 0;
585 BUF_HWCB_MTO_LOST = 0;
586 BUF_HWCB_CHAR_LOST = 0;
588 page = (unsigned long) OUT_HWCB;
590 ALL_HWCB_MTO -= OUT_HWCB_MTO;
591 ALL_HWCB_CHAR -= OUT_HWCB_CHAR;
592 hwc_data.hwcb_count--;
594 OUT_HWCB = OUT_HWCB_NEXT;
596 if (page >= hwc_data.kmem_start &&
597 page <= hwc_data.kmem_end) {
598 /*memset((void *) page, 0, PAGE_SIZE); */
600 page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
601 clear_bit (page_nr, &hwc_data.kmem_pages);
604 #ifdef BUFFER_STRESS_TEST
608 "*** " HWC_RW_PRINT_HEADER
609 "page at 0x%x released, %i pages still in use ***\n",
610 page, hwc_data.hwcb_count);
619 unsigned char *message,
620 unsigned short int count)
622 unsigned short int mto_size;
630 if (BUF_HWCB == hwc_data.current_hwcb)
633 mto_size = sizeof (mto_t) + count;
635 hwcb = (write_hwcb_t *) BUF_HWCB;
637 if ((MAX_HWCB_ROOM - hwcb->length) < mto_size)
640 mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length);
642 memcpy (mto, &mto_template, sizeof (mto_t));
644 dest = (void *) (((unsigned long) mto) + sizeof (mto_t));
646 memcpy (dest, message, count);
648 mto->length += count;
650 hwcb->length += mto_size;
651 hwcb->msgbuf.length += mto_size;
652 hwcb->msgbuf.mdb.length += mto_size;
656 BUF_HWCB_CHAR += count;
657 ALL_HWCB_CHAR += count;
662 static int write_event_data_1 (void);
665 do_poll_hwc (unsigned long data)
669 spin_lock_irqsave (&hwc_data.lock, flags);
671 write_event_data_1 ();
673 spin_unlock_irqrestore (&hwc_data.lock, flags);
677 start_poll_hwc (void)
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;
688 write_event_data_1 (void)
690 unsigned short int condition_code;
692 write_hwcb_t *hwcb = (write_hwcb_t *) OUT_HWCB;
694 if ((!hwc_data.write_prio) &&
695 (!hwc_data.write_nonprio) &&
696 hwc_data.read_statechange)
699 if (hwc_data.current_servc)
702 retval = sane_write_hwcb ();
709 if (!hwc_data.write_nonprio && hwc_data.write_prio)
710 hwcb->msgbuf.type = ET_PMsgCmd;
712 hwcb->msgbuf.type = ET_Msg;
714 condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB);
716 #ifdef DUMP_HWC_WRITE_ERROR
717 if (condition_code != HWC_COMMAND_INITIATED)
718 __asm__ ("LHI 1,0xe20\n\t"
723 : "a" (&condition_code), "a" (OUT_HWCB)
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;
736 case HWC_NOT_OPERATIONAL:
748 while (hwc_data.hwcb_count > 1)
749 release_write_hwcb ();
751 release_write_hwcb ();
753 hwc_data.flags &= ~HWC_FLUSH;
757 write_event_data_2 (u32 ext_int_param)
762 #ifdef DUMP_HWC_WRITE_ERROR
763 if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
764 != (unsigned long) hwc_data.current_hwcb) {
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,
777 hwcb = (write_hwcb_t *) OUT_HWCB;
779 #ifdef DUMP_HWC_WRITE_LIST_ERROR
780 if (((unsigned char *) hwcb) != hwc_data.current_hwcb) {
781 __asm__ ("LHI 1,0xe22\n\t"
789 "a" (hwc_data.current_hwcb),
792 : "1", "2", "3", "4", "5");
796 #ifdef DUMP_HWC_WRITE_ERROR
797 if (hwcb->response_code != 0x0020) {
798 __asm__ ("LHI 1,0xe21\n\t"
806 : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
808 "a" (&(hwc_data.hwcb_count))
809 : "1", "2", "3", "4", "5");
813 switch (hwcb->response_code) {
816 retval = OUT_HWCB_CHAR;
817 release_write_hwcb ();
822 if (!hwc_data.read_statechange) {
823 hwcb->response_code = 0;
832 "write_event_data_2 : "
834 "(response code: 0x%x "
835 "HWCB address: 0x%x).\n",
841 if (retval == -EIO) {
843 hwcb->control_mask[0] = 0;
844 hwcb->control_mask[1] = 0;
845 hwcb->control_mask[2] = 0;
846 hwcb->response_code = 0;
848 hwc_data.current_servc = 0;
849 hwc_data.current_hwcb = NULL;
851 if (hwc_data.flags & HWC_FLUSH)
859 unsigned char *message,
860 unsigned short count)
863 if (add_mto (message, count) != count) {
865 if (allocate_write_hwcb () < 0)
868 #ifdef DUMP_HWC_WRITE_LIST_ERROR
869 if (add_mto (message, count) != count)
870 __asm__ ("LHI 1,0xe32\n\t"
877 : "a" (message), "a" (&hwc_data.kmem_pages),
878 "a" (BUF_HWCB), "a" (OUT_HWCB)
879 : "1", "2", "3", "4", "5");
881 add_mto (message, count);
888 unsigned char *message,
889 unsigned short count)
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;
896 hwc_data.obuf_start += count;
898 do_put_line (message, count);
900 hwc_data.obuf_start -= count;
908 if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb))
909 allocate_write_hwcb ();
911 hwcb = (write_hwcb_t *) BUF_HWCB;
912 hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm;
916 hwc_write_timeout (unsigned long data)
920 spin_lock_irqsave (&hwc_data.lock, flags);
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;
927 hwc_data.obuf_cursor = 0;
928 hwc_data.obuf_count = 0;
930 write_event_data_1 ();
932 spin_unlock_irqrestore (&hwc_data.lock, flags);
940 unsigned char write_time)
942 unsigned int i_msg = 0;
943 unsigned short int spaces = 0;
944 unsigned int processed_characters = 0;
946 unsigned short int obuf_count;
947 unsigned short int obuf_cursor;
948 unsigned short int obuf_columns;
950 if (hwc_data.obuf_start) {
953 obuf_columns = MIN (hwc_data.ioctls.columns,
954 MAX_MESSAGE_SIZE - hwc_data.obuf_start);
956 obuf_cursor = hwc_data.obuf_cursor;
957 obuf_count = hwc_data.obuf_count;
958 obuf_columns = hwc_data.ioctls.columns;
961 for (i_msg = 0; i_msg < count; i_msg++) {
963 get_user (ch, msg + i_msg);
967 processed_characters++;
969 if ((obuf_cursor == obuf_columns) &&
974 put_line (&hwc_data.obuf[hwc_data.obuf_start],
983 put_line (&hwc_data.obuf[hwc_data.obuf_start],
991 hwc_data.obuf_start += obuf_count;
993 hwc_data.obuf_start -= obuf_count;
1000 if (obuf_cursor < obuf_columns) {
1001 hwc_data.obuf[hwc_data.obuf_start +
1007 } while (obuf_cursor % hwc_data.ioctls.width_htab);
1014 spaces = obuf_cursor;
1015 put_line (&hwc_data.obuf[hwc_data.obuf_start],
1017 obuf_count = obuf_cursor;
1019 hwc_data.obuf[hwc_data.obuf_start +
1020 obuf_cursor - spaces]
1040 put_line (&hwc_data.obuf[hwc_data.obuf_start],
1049 hwc_data.obuf[hwc_data.obuf_start +
1053 if (obuf_cursor > obuf_count)
1054 obuf_count = obuf_cursor;
1059 if (hwc_data.obuf_start ||
1060 (hwc_data.ioctls.final_nl == 0)) {
1062 put_line (&hwc_data.obuf[hwc_data.obuf_start],
1068 if (hwc_data.ioctls.final_nl > 0) {
1070 if (hwc_data.flags & HWC_WTIMER_RUNS) {
1072 mod_timer (&hwc_data.write_timer,
1073 jiffies + hwc_data.ioctls.final_nl * HZ / 10);
1076 init_timer (&hwc_data.write_timer);
1077 hwc_data.write_timer.function =
1079 hwc_data.write_timer.data =
1080 (unsigned long) NULL;
1081 hwc_data.write_timer.expires =
1083 hwc_data.ioctls.final_nl * HZ / 10;
1084 add_timer (&hwc_data.write_timer);
1085 hwc_data.flags |= HWC_WTIMER_RUNS;
1094 if (!hwc_data.obuf_start) {
1095 hwc_data.obuf_cursor = obuf_cursor;
1096 hwc_data.obuf_count = obuf_count;
1098 if (write_time == IMMEDIATE_WRITE)
1099 write_event_data_1 ();
1101 return processed_characters;
1105 hwc_write (int from_user, const unsigned char *msg, unsigned int count)
1107 unsigned long flags;
1110 spin_lock_irqsave (&hwc_data.lock, flags);
1112 retval = do_hwc_write (from_user, (unsigned char *) msg,
1113 count, IMMEDIATE_WRITE);
1115 spin_unlock_irqrestore (&hwc_data.lock, flags);
1121 hwc_chars_in_buffer (unsigned char flag)
1123 unsigned short int number = 0;
1124 unsigned long flags;
1126 spin_lock_irqsave (&hwc_data.lock, flags);
1129 number += ALL_HWCB_CHAR;
1131 if (flag & IN_WRITE_BUF)
1132 number += hwc_data.obuf_cursor;
1134 spin_unlock_irqrestore (&hwc_data.lock, flags);
1140 nr_setbits (kmem_pages_t arg)
1145 for (i = 0; i < (sizeof (arg) << 3); i++) {
1155 hwc_write_room (unsigned char flag)
1157 unsigned int number = 0;
1158 unsigned long flags;
1161 spin_lock_irqsave (&hwc_data.lock, flags);
1163 if (flag & IN_HWCB) {
1166 hwcb = (write_hwcb_t *) BUF_HWCB;
1167 number += MAX_HWCB_ROOM - hwcb->length;
1169 number += (hwc_data.ioctls.kmem_hwcb -
1170 nr_setbits (hwc_data.kmem_pages)) *
1172 (sizeof (write_hwcb_t) + sizeof (mto_t)));
1174 if (flag & IN_WRITE_BUF)
1175 number += MAX_HWCB_ROOM - hwc_data.obuf_cursor;
1177 spin_unlock_irqrestore (&hwc_data.lock, flags);
1183 hwc_flush_buffer (unsigned char flag)
1185 unsigned long flags;
1187 spin_lock_irqsave (&hwc_data.lock, flags);
1189 if (flag & IN_HWCB) {
1190 if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
1193 hwc_data.flags |= HWC_FLUSH;
1195 if (flag & IN_WRITE_BUF) {
1196 hwc_data.obuf_cursor = 0;
1197 hwc_data.obuf_count = 0;
1199 spin_unlock_irqrestore (&hwc_data.lock, flags);
1203 seperate_cases (unsigned char *buf, unsigned short int count)
1206 unsigned short int i_in;
1208 unsigned short int i_out = 0;
1210 unsigned char _case = 0;
1212 for (i_in = 0; i_in < count; i_in++) {
1214 if (buf[i_in] == hwc_data.ioctls.delim) {
1216 if ((i_in + 1 < count) &&
1217 (buf[i_in + 1] == hwc_data.ioctls.delim)) {
1219 buf[i_out] = hwc_data.ioctls.delim;
1232 if (hwc_data.ioctls.tolower)
1233 buf[i_out] = _ebc_toupper[buf[i_in]];
1236 buf[i_out] = _ebc_tolower[buf[i_in]];
1239 buf[i_out] = buf[i_in];
1248 #ifdef DUMP_HWCB_INPUT
1251 gds_vector_name (u16 id, unsigned char name[])
1257 name = "Multiple Domain Support Message Unit";
1259 case GDS_ID_MDSRouteInfo:
1260 name = "MDS Routing Information";
1262 case GDS_ID_AgUnWrkCorr:
1263 name = "Agent Unit of Work Correlator";
1265 case GDS_ID_SNACondReport:
1266 name = "SNA Condition Report";
1269 name = "CP Management Services Unit";
1271 case GDS_ID_RoutTargInstr:
1272 name = "Routing and Targeting Instructions";
1275 name = "Operate Request";
1277 case GDS_ID_TextCmd:
1278 name = "Text Command";
1282 name = "unknown GDS variable";
1290 inline static gds_vector_t *
1292 gds_vector_t * start, void *end, u16 id)
1295 gds_vector_t *retval = NULL;
1299 while (((void *) vec) < end) {
1300 if (vec->gds_id == id) {
1302 #ifdef DUMP_HWCB_INPUT
1304 unsigned char name[64];
1306 retval_name = gds_vector_name (id, name);
1310 "%s at 0x%x up to 0x%x, length: %d",
1312 (unsigned long) vec,
1313 ((unsigned long) vec) + vec->length - 1,
1315 if (retval_name < 0)
1329 vec = (gds_vector_t *) (((unsigned long) vec) + vec->length);
1335 inline static gds_subvector_t *
1336 find_gds_subvector (
1337 gds_subvector_t * start, void *end, u8 key)
1339 gds_subvector_t *subvec;
1340 gds_subvector_t *retval = NULL;
1344 while (((void *) subvec) < end) {
1345 if (subvec->key == key) {
1349 subvec = (gds_subvector_t *)
1350 (((unsigned long) subvec) + subvec->length);
1357 get_input (void *start, void *end)
1361 count = ((unsigned long) end) - ((unsigned long) start);
1363 if (hwc_data.ioctls.tolower)
1364 EBC_TOLOWER (start, count);
1366 if (hwc_data.ioctls.delim)
1367 count = seperate_cases (start, count);
1369 HWC_EBCASC_STR (start, count);
1371 if (hwc_data.ioctls.echo)
1372 do_hwc_write (0, start, count, IMMEDIATE_WRITE);
1374 if (hwc_data.calls != NULL)
1375 if (hwc_data.calls->move_input != NULL)
1376 (hwc_data.calls->move_input) (start, count);
1382 eval_selfdeftextmsg (gds_subvector_t * start, void *end)
1384 gds_subvector_t *subvec;
1391 while (((void *) subvec) < end) {
1392 subvec = find_gds_subvector (subvec, end, 0x30);
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;
1408 eval_textcmd (gds_subvector_t * start, void *end)
1410 gds_subvector_t *subvec;
1411 gds_subvector_t *subvec_data;
1417 while (((void *) subvec) < end) {
1418 subvec = find_gds_subvector (
1419 subvec, end, GDS_KEY_SelfDefTextMsg);
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;
1435 eval_cpmsu (gds_vector_t * start, void *end)
1438 gds_subvector_t *vec_data;
1444 while (((void *) vec) < end) {
1445 vec = find_gds_vector (vec, end, GDS_ID_TextCmd);
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;
1459 eval_mdsmu (gds_vector_t * start, void *end)
1462 gds_vector_t *vec_data;
1466 vec = find_gds_vector (start, end, GDS_ID_CPMSU);
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);
1477 eval_evbuf (gds_vector_t * start, void *end)
1480 gds_vector_t *vec_data;
1484 vec = find_gds_vector (start, end, GDS_ID_MDSMU);
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);
1495 eval_hwc_receive_mask (_hwcb_mask_t mask)
1498 hwc_data.write_nonprio
1499 = ((mask & ET_Msg_Mask) == ET_Msg_Mask);
1502 = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
1504 if (hwc_data.write_prio || hwc_data.write_nonprio) {
1508 "can write messages\n");
1514 "can not write messages\n");
1520 eval_hwc_send_mask (_hwcb_mask_t mask)
1523 hwc_data.read_statechange
1524 = ((mask & ET_StateChange_Mask) == ET_StateChange_Mask);
1525 if (hwc_data.read_statechange)
1529 "can read state change notifications\n");
1534 "can not read state change notifications\n");
1536 hwc_data.sig_quiesce
1537 = ((mask & ET_SigQuiesce_Mask) == ET_SigQuiesce_Mask);
1538 if (hwc_data.sig_quiesce)
1542 "can receive signal quiesce\n");
1547 "can not receive signal quiesce\n");
1549 hwc_data.read_nonprio
1550 = ((mask & ET_OpCmd_Mask) == ET_OpCmd_Mask);
1551 if (hwc_data.read_nonprio)
1555 "can read commands\n");
1558 = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
1559 if (hwc_data.read_prio)
1563 "can read priority commands\n");
1565 if (hwc_data.read_prio || hwc_data.read_nonprio) {
1571 "can not read commands from operator\n");
1577 eval_statechangebuf (statechangebuf_t * scbuf)
1584 "HWC state change detected\n");
1586 if (scbuf->validity_hwc_active_facility_mask) {
1589 if (scbuf->validity_hwc_receive_mask) {
1591 if (scbuf->mask_length != 4) {
1592 #ifdef DUMP_HWC_INIT_ERROR
1593 __asm__ ("LHI 1,0xe50\n\t"
1602 retval += eval_hwc_receive_mask
1603 (scbuf->hwc_receive_mask);
1606 if (scbuf->validity_hwc_send_mask) {
1608 if (scbuf->mask_length != 4) {
1609 #ifdef DUMP_HWC_INIT_ERROR
1610 __asm__ ("LHI 1,0xe51\n\t"
1619 retval += eval_hwc_send_mask
1620 (scbuf->hwc_send_mask);
1623 if (scbuf->validity_read_data_function_mask) {
1630 extern unsigned long cpu_online_map;
1631 static volatile unsigned long cpu_quiesce_map;
1634 do_load_quiesce_psw (void)
1638 clear_bit (smp_processor_id (), &cpu_quiesce_map);
1639 if (smp_processor_id () == 0) {
1641 while (cpu_quiesce_map != 0) ;
1643 quiesce_psw.mask = _DW_PSW_MASK;
1644 quiesce_psw.addr = 0xfff;
1645 __load_psw (quiesce_psw);
1647 signal_processor (smp_processor_id (), sigp_stop);
1651 do_machine_quiesce (void)
1653 cpu_quiesce_map = cpu_online_map;
1654 smp_call_function (do_load_quiesce_psw, NULL, 0, 0);
1655 do_load_quiesce_psw ();
1660 do_machine_quiesce (void)
1664 quiesce_psw.mask = _DW_PSW_MASK;
1665 queisce_psw.addr = 0xfff;
1666 __load_psw (quiesce_psw);
1672 process_evbufs (void *start, void *end)
1677 gds_vector_t *evbuf_data;
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) {
1686 case ET_CntlProgOpCmd:
1688 #ifdef DUMP_HWCB_INPUT
1694 "at 0x%x up to 0x%x, length: %d\n",
1695 (unsigned long) evbuf,
1696 (unsigned long) (evbuf_end - 1),
1698 dump_storage_area ((void *) evbuf, evbuf->length);
1700 retval += eval_evbuf (evbuf_data, evbuf_end);
1702 case ET_StateChange:
1703 retval += eval_statechangebuf
1704 ((statechangebuf_t *) evbuf);
1708 _machine_restart = do_machine_quiesce;
1709 _machine_halt = do_machine_quiesce;
1710 _machine_power_off = do_machine_quiesce;
1717 "unconditional read: "
1718 "unknown event buffer found, "
1723 evbuf = (evbuf_t *) evbuf_end;
1729 unconditional_read_1 (void)
1731 unsigned short int condition_code;
1732 read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
1737 if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio))
1740 if (hwc_data.current_servc)
1744 memset (hwcb, 0x00, PAGE_SIZE);
1745 memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t));
1747 condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page);
1749 #ifdef DUMP_HWC_READ_ERROR
1750 if (condition_code == HWC_NOT_OPERATIONAL)
1751 __asm__ ("LHI 1,0xe40\n\t"
1756 : "a" (&condition_code), "a" (hwc_data.page)
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;
1777 unconditional_read_2 (u32 ext_int_param)
1779 read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
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"
1791 : "a" (hwc_data.page), "a" (&(hwcb->response_code))
1795 hwc_data.current_servc = 0;
1796 hwc_data.current_hwcb = NULL;
1798 switch (hwcb->response_code) {
1802 return process_evbufs (
1803 (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)),
1804 (void *) (((unsigned long) hwcb) + hwcb->length));
1811 "unconditional read: "
1812 "got interrupt and tried to read input, "
1813 "but nothing found (response code=0x%x).\n",
1814 hwcb->response_code);
1821 "unconditional read: HWCB boundary violation - this "
1822 "must not occur in a correct driver, please contact "
1830 "unconditional read: "
1831 "insufficient HWCB length - this must not occur in a "
1832 "correct driver, please contact author\n");
1839 "unconditional read: "
1840 "invalid command - this must not occur in a correct "
1841 "driver, please contact author\n");
1848 "unconditional read: invalid function code\n");
1855 "unconditional read: invalid selection mask\n");
1862 "unconditional read: HWC equipment check\n");
1869 "unconditional read: invalid response code %x - this "
1870 "must not occur in a correct driver, please contact "
1872 hwcb->response_code);
1878 write_event_mask_1 (void)
1880 unsigned int condition_code;
1883 condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);
1885 #ifdef DUMP_HWC_INIT_ERROR
1887 if (condition_code == HWC_NOT_OPERATIONAL)
1888 __asm__ ("LHI 1,0xe10\n\t"
1893 : "a" (&condition_code), "a" (hwc_data.page)
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;
1914 write_event_mask_2 (u32 ext_int_param)
1916 init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;
1919 if (hwcb->response_code != 0x0020) {
1920 #ifdef DUMP_HWC_INIT_ERROR
1921 __asm__ ("LHI 1,0xe11\n\t"
1926 : "a" (hwcb), "a" (&(hwcb->response_code))
1932 if (hwcb->mask_length != 4) {
1933 #ifdef DUMP_HWC_INIT_ERROR
1934 __asm__ ("LHI 1,0xe52\n\t"
1942 retval += eval_hwc_receive_mask
1943 (hwcb->hwc_receive_mask);
1944 retval += eval_hwc_send_mask (hwcb->hwc_send_mask);
1948 hwc_data.current_servc = 0;
1949 hwc_data.current_hwcb = NULL;
1955 set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct)
1960 if (ioctls->width_htab > MAX_MESSAGE_SIZE) {
1962 tmp.width_htab = MAX_MESSAGE_SIZE;
1966 tmp.width_htab = ioctls->width_htab;
1968 tmp.echo = ioctls->echo;
1970 if (ioctls->columns > MAX_MESSAGE_SIZE) {
1972 tmp.columns = MAX_MESSAGE_SIZE;
1976 tmp.columns = ioctls->columns;
1978 tmp.final_nl = ioctls->final_nl;
1980 if (ioctls->max_hwcb < 2) {
1986 tmp.max_hwcb = ioctls->max_hwcb;
1988 tmp.tolower = ioctls->tolower;
1990 if (ioctls->kmem_hwcb > ioctls->max_hwcb) {
1992 tmp.kmem_hwcb = ioctls->max_hwcb;
1996 tmp.kmem_hwcb = ioctls->kmem_hwcb;
1998 if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) {
2000 ioctls->kmem_hwcb = MAX_KMEM_PAGES;
2004 if (ioctls->kmem_hwcb < 2) {
2006 ioctls->kmem_hwcb = 2;
2010 tmp.delim = ioctls->delim;
2013 hwc_data.ioctls = tmp;
2023 memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
2027 retval = write_event_mask_1 ();
2029 if (retval == -EBUSY) {
2031 hwc_data.flags |= HWC_INIT;
2033 __ctl_store (cr0, 0, 0);
2037 __ctl_load (cr0, 0, 0);
2039 asm volatile ("STOSM %0,0x01"
2040 :"=m" (psw_mask)::"memory");
2042 while (!(hwc_data.flags & HWC_INTERRUPT))
2045 asm volatile ("STNSM %0,0xFE"
2046 :"=m" (psw_mask)::"memory");
2048 __ctl_load (cr0_save, 0, 0);
2050 hwc_data.flags &= ~HWC_INIT;
2052 } while (retval == -EBUSY);
2054 if (retval == -EIO) {
2055 hwc_data.flags |= HWC_BROKEN;
2056 printk (HWC_RW_PRINT_HEADER "HWC not operational\n");
2061 void hwc_interrupt_handler (struct pt_regs *regs, __u16 code);
2068 #ifdef BUFFER_STRESS_TEST
2075 if (register_early_external_interrupt (0x2401, hwc_interrupt_handler,
2076 &ext_int_info_hwc) != 0)
2077 panic ("Couldn't request external interrupts 0x2401");
2079 spin_lock_init (&hwc_data.lock);
2081 #ifdef USE_VM_DETECTION
2083 if (MACHINE_IS_VM) {
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;
2091 hwc_data.init_ioctls.tolower = 0;
2092 hwc_data.init_ioctls.delim = 0;
2095 retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
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;
2102 retval = do_hwc_init ();
2106 #ifdef BUFFER_STRESS_TEST
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;
2118 "This is stress test message #%i, free: %i bytes\n",
2120 MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t)));
2125 return /*retval */ 0;
2129 hwc_register_calls (hwc_high_level_calls_t * calls)
2134 if (hwc_data.calls != NULL)
2137 hwc_data.calls = calls;
2142 hwc_unregister_calls (hwc_high_level_calls_t * calls)
2144 if (hwc_data.calls == NULL)
2147 if (calls != hwc_data.calls)
2150 hwc_data.calls = NULL;
2155 hwc_send (hwc_request_t * req)
2157 unsigned long flags;
2161 spin_lock_irqsave (&hwc_data.lock, flags);
2162 if (!req || !req->callback || !req->block) {
2166 if (hwc_data.request) {
2170 cc = service_call (req->word, req->block);
2173 hwc_data.request = req;
2174 hwc_data.current_servc = req->word;
2175 hwc_data.current_hwcb = req->block;
2186 spin_unlock_irqrestore (&hwc_data.lock, flags);
2190 EXPORT_SYMBOL (hwc_send);
2193 do_hwc_callback (u32 ext_int_param)
2195 if (!hwc_data.request || !hwc_data.request->callback)
2197 if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
2198 != (unsigned long) hwc_data.request->block)
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;
2207 hwc_do_interrupt (u32 ext_int_param)
2209 u32 finished_hwcb = ext_int_param & HWC_EXT_INT_PARAM_ADDR;
2210 u32 evbuf_pending = ext_int_param & HWC_EXT_INT_PARAM_PEND;
2212 if (hwc_data.flags & HWC_PTIMER_RUNS) {
2213 del_timer (&hwc_data.poll_timer);
2214 hwc_data.flags &= ~HWC_PTIMER_RUNS;
2216 if (finished_hwcb) {
2218 if ((unsigned long) hwc_data.current_hwcb != finished_hwcb) {
2222 "interrupt: mismatch: "
2223 "ext. int param. (0x%x) vs. "
2224 "current HWCB (0x%x)\n",
2226 hwc_data.current_hwcb);
2228 if (hwc_data.request) {
2230 do_hwc_callback (ext_int_param);
2233 switch (hwc_data.current_servc) {
2235 case HWC_CMDW_WRITEMASK:
2237 write_event_mask_2 (ext_int_param);
2240 case HWC_CMDW_WRITEDATA:
2242 write_event_data_2 (ext_int_param);
2245 case HWC_CMDW_READDATA:
2247 unconditional_read_2 (ext_int_param);
2255 if (hwc_data.current_hwcb) {
2259 "interrupt: mismatch: "
2260 "ext. int. param. (0x%x) vs. "
2261 "current HWCB (0x%x)\n",
2263 hwc_data.current_hwcb);
2267 if (evbuf_pending) {
2269 unconditional_read_1 ();
2272 write_event_data_1 ();
2275 if (!hwc_data.calls || !hwc_data.calls->wake_up)
2277 (hwc_data.calls->wake_up) ();
2281 hwc_interrupt_handler (struct pt_regs *regs, __u16 code)
2283 int cpu = smp_processor_id ();
2285 u32 ext_int_param = hwc_ext_int_param ();
2287 irq_enter (cpu, 0x2401);
2289 if (hwc_data.flags & HWC_INIT) {
2291 hwc_data.flags |= HWC_INTERRUPT;
2292 } else if (hwc_data.flags & HWC_BROKEN) {
2294 if (!do_hwc_init ()) {
2295 hwc_data.flags &= ~HWC_BROKEN;
2296 internal_print (DELAYED_WRITE,
2298 "delayed HWC setup after"
2299 " temporary breakdown"
2300 " (ext. int. parameter=0x%x)\n",
2304 spin_lock (&hwc_data.lock);
2305 hwc_do_interrupt (ext_int_param);
2306 spin_unlock (&hwc_data.lock);
2308 irq_exit (cpu, 0x2401);
2315 spin_lock (&hwc_data.lock);
2316 spin_unlock (&hwc_data.lock);
2318 __ctl_store (cr0, 0, 0);
2322 __ctl_load (cr0, 0, 0);
2324 asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");
2326 while (ALL_HWCB_CHAR)
2329 asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");
2331 __ctl_load (cr0_save, 0, 0);
2335 hwc_ioctl (unsigned int cmd, unsigned long arg)
2337 hwc_ioctls_t tmp = hwc_data.ioctls;
2339 unsigned long flags;
2342 spin_lock_irqsave (&hwc_data.lock, flags);
2347 if (get_user (tmp.width_htab, (ioctl_htab_t *) arg))
2352 if (get_user (tmp.echo, (ioctl_echo_t *) arg))
2357 if (get_user (tmp.columns, (ioctl_cols_t *) arg))
2362 if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))
2367 if (get_user (obuf, (unsigned int *) arg))
2370 tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12);
2372 tmp.max_hwcb = (obuf >> 12);
2376 if (get_user (tmp.tolower, (ioctl_case_t *) arg))
2381 if (get_user (tmp.delim, (ioctl_delim_t *) arg))
2386 retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
2390 if (put_user (tmp.width_htab, (ioctl_htab_t *) arg))
2395 if (put_user (tmp.echo, (ioctl_echo_t *) arg))
2400 if (put_user (tmp.columns, (ioctl_cols_t *) arg))
2405 if (put_user (tmp.final_nl, (ioctl_nl_t *) arg))
2410 if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg))
2415 if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg))
2420 if (put_user (tmp.tolower, (ioctl_case_t *) arg))
2425 if (put_user (tmp.delim, (ioctl_delim_t *) arg))
2431 if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg))
2436 if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg))
2445 if (_IOC_DIR (cmd) == _IOC_WRITE)
2446 retval = set_hwc_ioctls (&tmp, 0);
2454 retval = -ENOIOCTLCMD;
2456 spin_unlock_irqrestore (&hwc_data.lock, flags);