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
internal_print(char write_time,char * fmt,...)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
hwc_printk(const char * fmt,...)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
dump_storage_area(unsigned char * area,unsigned short int count)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
service_call(u32 hwc_command_word,unsigned char hwcb[])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
hwc_ext_int_param(void)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
prepare_write_hwcb(void)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
sane_write_hwcb(void)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
reuse_write_hwcb(void)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
allocate_write_hwcb(void)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
release_write_hwcb(void)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
add_mto(unsigned char * message,unsigned short int count)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
do_poll_hwc(unsigned long data)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
start_poll_hwc(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
write_event_data_1(void)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
flush_hwcbs(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
write_event_data_2(u32 ext_int_param)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
do_put_line(unsigned char * message,unsigned short count)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
put_line(unsigned char * message,unsigned short count)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
set_alarm(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
hwc_write_timeout(unsigned long data)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
do_hwc_write(int from_user,unsigned char * msg,unsigned int count,unsigned char write_time)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
hwc_write(int from_user,const unsigned char * msg,unsigned int count)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
hwc_chars_in_buffer(unsigned char flag)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
nr_setbits(kmem_pages_t arg)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
hwc_write_room(unsigned char flag)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
hwc_flush_buffer(unsigned char flag)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
seperate_cases(unsigned char * buf,unsigned short int count)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
gds_vector_name(u16 id,unsigned char name[])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 *
find_gds_vector(gds_vector_t * start,void * end,u16 id)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 *
find_gds_subvector(gds_subvector_t * start,void * end,u8 key)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
get_input(void * start,void * end)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
eval_selfdeftextmsg(gds_subvector_t * start,void * end)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
eval_textcmd(gds_subvector_t * start,void * end)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
eval_cpmsu(gds_vector_t * start,void * end)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
eval_mdsmu(gds_vector_t * start,void * end)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
eval_evbuf(gds_vector_t * start,void * end)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
eval_hwc_receive_mask(_hwcb_mask_t mask)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
eval_hwc_send_mask(_hwcb_mask_t mask)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
eval_statechangebuf(statechangebuf_t * scbuf)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
do_load_quiesce_psw(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
do_machine_quiesce(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
do_machine_quiesce(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
process_evbufs(void * start,void * end)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
unconditional_read_1(void)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
unconditional_read_2(u32 ext_int_param)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
write_event_mask_1(void)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
write_event_mask_2(u32 ext_int_param)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
set_hwc_ioctls(hwc_ioctls_t * ioctls,char correct)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
do_hwc_init(void)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
hwc_init(void)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
hwc_register_calls(hwc_high_level_calls_t * calls)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
hwc_unregister_calls(hwc_high_level_calls_t * calls)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
hwc_send(hwc_request_t * req)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
do_hwc_callback(u32 ext_int_param)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
hwc_do_interrupt(u32 ext_int_param)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
hwc_interrupt_handler(struct pt_regs * regs,__u16 code)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
hwc_unblank(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
hwc_ioctl(unsigned int cmd,unsigned long arg)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 }
2459