patch-2.4.2 linux/drivers/s390/char/hwc_rw.c

Next file: linux/drivers/s390/char/hwc_rw.h
Previous file: linux/drivers/s390/char/hwc_con.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc_rw.c linux/drivers/s390/char/hwc_rw.c
@@ -6,14 +6,13 @@
  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Peschke <peschke@fh-brandenburg.de>
  *
+ * 
  *
- *
- *
- *
- *
+ * 
+ * 
+ * 
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -28,6 +27,7 @@
 #include <asm/bitops.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/s390_ext.h>
 
 #ifndef MIN
 #define MIN(a,b) ((a<b) ? a : b)
@@ -118,12 +118,16 @@
 static unsigned char
  _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 
-typedef u32 kmem_pages_t;
+/* pedantic: long because we use set_bit on it --RR */
+typedef long kmem_pages_t;
 
 #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
 
 #define HWC_TIMER_RUNS	1
-#define FLUSH_HWCBS	2
+#define HWC_FLUSH	2
+#define HWC_INIT	4
+#define HWC_BROKEN	8
+#define HWC_INTERRUPT	16
 
 static struct {
 
@@ -168,6 +172,8 @@
 
 	unsigned char flags;
 
+	hwc_high_level_calls_t *calls;
+
 	spinlock_t lock;
 
 	struct timer_list write_timer;
@@ -179,7 +185,6 @@
 		8,
 		    0,
 		    80,
-		    CODE_ASCII,
 		    1,
 		    50,
 		    MAX_KMEM_PAGES,
@@ -208,20 +213,24 @@
 	    0,
 	    0,
 	    0,
-	    0
+	    0,
+	    NULL
 
 };
 
+static unsigned long cr0 __attribute__ ((aligned (8)));
+static unsigned long cr0_save __attribute__ ((aligned (8)));
+static unsigned char psw_mask __attribute__ ((aligned (8)));
+
 #define DELAYED_WRITE 0
 #define IMMEDIATE_WRITE 1
 
 static signed int do_hwc_write (int from_user, unsigned char *,
 				unsigned int,
-				unsigned char,
 				unsigned char);
 
 static asmlinkage int 
-internal_print (char write_time, const char *fmt,...)
+internal_print (char write_time, char *fmt,...)
 {
 	va_list args;
 	int i;
@@ -230,7 +239,7 @@
 	va_start (args, fmt);
 	i = vsprintf (buf, fmt, args);
 	va_end (args);
-	return do_hwc_write (0, buf, i, CODE_ASCII, write_time);
+	return do_hwc_write (0, buf, i, write_time);
 }
 
 int 
@@ -246,7 +255,7 @@
 
 	i = vsprintf (buf, fmt, args);
 	va_end (args);
-	retval = do_hwc_write (0, buf, i, CODE_ASCII, IMMEDIATE_WRITE);
+	retval = do_hwc_write (0, buf, i, IMMEDIATE_WRITE);
 
 	spin_unlock_irqrestore (&hwc_data.lock, flags);
 
@@ -296,8 +305,8 @@
 {
 	unsigned int condition_code = 1;
 
-	__asm__ __volatile__ ("L 1, 0(0,%0) \n\t"
-			      "LRA 2, 0(0,%1) \n\t"
+	__asm__ __volatile__ ("L 1, 0(%0) \n\t"
+			      "LRA 2, 0(%1) \n\t"
 			      ".long 0xB2200012 \n\t"
 			      :
 			      :"a" (&hwc_command_word), "a" (hwcb)
@@ -315,7 +324,7 @@
 {
 	u32 param;
 
-	__asm__ __volatile__ ("L %0,128(0,0)\n\t"
+	__asm__ __volatile__ ("L %0,128\n\t"
 			      :"=r" (param));
 
 	return ((unsigned char *) param);
@@ -361,7 +370,7 @@
 
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		__asm__ ("LHI 1,0xe30\n\t"
-			 "LRA 2,0(0,%0) \n\t"
+			 "LRA 2,0(%0) \n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (bad_addr)
@@ -392,7 +401,7 @@
 			page = (unsigned long) BUF_HWCB;
 
 			if (page >= hwc_data.kmem_start &&
-			    page < hwc_data.kmem_end) {
+			    page <= hwc_data.kmem_end) {
 
 				page_nr = (int)
 				    ((page - hwc_data.kmem_start) >> 12);
@@ -423,8 +432,8 @@
 	if (hwc_data.hwcb_count < 2)
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		__asm__ ("LHI 1,0xe31\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (BUF_HWCB), "a" (OUT_HWCB)
@@ -510,7 +519,7 @@
 		    (hwc_data.kmem_start + (page_nr << 12));
 		set_bit (page_nr, &hwc_data.kmem_pages);
 	} else
-		page = (unsigned char *) __get_free_page (GFP_ATOMIC);
+		page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);
 
 	if (!page)
 		return -ENOMEM;
@@ -573,9 +582,8 @@
 		OUT_HWCB = OUT_HWCB_NEXT;
 
 		if (page >= hwc_data.kmem_start &&
-		    page < hwc_data.kmem_end) {
-
-			memset ((void *) page, 0, PAGE_SIZE);
+		    page <= hwc_data.kmem_end) {
+			/*memset((void *) page, 0, PAGE_SIZE); */
 
 			page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
 			clear_bit (page_nr, &hwc_data.kmem_pages);
@@ -663,8 +671,8 @@
 #ifdef DUMP_HWC_WRITE_ERROR
 	if (condition_code != HWC_COMMAND_INITIATED)
 		__asm__ ("LHI 1,0xe20\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (OUT_HWCB)
@@ -695,7 +703,7 @@
 
 	release_write_hwcb ();
 
-	hwc_data.flags &= ~FLUSH_HWCBS;
+	hwc_data.flags &= ~HWC_FLUSH;
 }
 
 static int 
@@ -703,79 +711,81 @@
 {
 	write_hwcb_t *hwcb;
 	int retval;
+
+#ifdef DUMP_HWC_WRITE_ERROR
 	unsigned char *param;
 
 	param = ext_int_param ();
-	if (param != hwc_data.current_hwcb)
+	if (param != hwc_data.current_hwcb) {
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "write_event_mask_2 : "
+				       "HWCB address does not fit "
+				       "(expected: 0x%x, got: 0x%x).\n",
+				       hwc_data.current_hwcb,
+				       param);
 		return -EINVAL;
+	}
+#endif
 
 	hwcb = (write_hwcb_t *) OUT_HWCB;
 
-#ifdef DUMP_HWC_WRITE_ERROR
-#if 0
-	if (((unsigned char *) hwcb) != param)
+#ifdef DUMP_HWC_WRITE_LIST_ERROR
+	if (((unsigned char *) hwcb) != hwc_data.current_hwcb) {
 		__asm__ ("LHI 1,0xe22\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
-			 "LRA 4,0(0,%2)\n\t"
-			 "LRA 5,0(0,%3)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
+			 "LRA 4,0(%2)\n\t"
+			 "LRA 5,0(%3)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (OUT_HWCB),
 			 "a" (hwc_data.current_hwcb),
 			 "a" (BUF_HWCB),
-			 "a" (param)
+			 "a" (hwcb)
 	      :	 "1", "2", "3", "4", "5");
+	}
 #endif
-	if (hwcb->response_code != 0x0020)
-#if 0
-		internal_print (DELAYED_WRITE, HWC_RW_PRINT_HEADER
-		  "\n************************ error in write_event_data_2()\n"
-				"OUT_HWCB:                    0x%x\n"
-				"BUF_HWCB:                    0x%x\n"
-				"response_code:               0x%x\n"
-				"hwc_data.hwcb_count:        %d\n"
-				"hwc_data.kmem_pages:        0x%x\n"
-				"hwc_data.ioctls.kmem_hwcb:   %d\n"
-				"hwc_data.ioctls.max_hwcb:    %d\n"
-				"hwc_data.kmem_start:        0x%x\n"
-				"hwc_data.kmem_end:          0x%x\n"
-		    "*****************************************************\n",
-				OUT_HWCB,
-				BUF_HWCB,
-				hwcb->response_code,
-				hwc_data.hwcb_count,
-				hwc_data.kmem_pages,
-				hwc_data.ioctls.kmem_hwcb,
-				hwc_data.ioctls.max_hwcb,
-				hwc_data.kmem_start,
-				hwc_data.kmem_end);
-#endif
-	__asm__ ("LHI 1,0xe21\n\t"
-		 "LRA 2,0(0,%0)\n\t"
-		 "LRA 3,0(0,%1)\n\t"
-		 "LRA 4,0(0,%2)\n\t"
-		 "LH 5,0(0,%3)\n\t"
-		 "SRL 5,8(0)\n\t"
-		 "J .+0 \n\t"
-      :
-      :	 "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
-		 "a" (BUF_HWCB),
-		 "a" (&(hwc_data.hwcb_count))
-      :	 "1", "2", "3", "4", "5");
+
+#ifdef DUMP_HWC_WRITE_ERROR
+	if (hwcb->response_code != 0x0020) {
+		__asm__ ("LHI 1,0xe21\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
+			 "LRA 4,0(%2)\n\t"
+			 "LH 5,0(%3)\n\t"
+			 "SRL 5,8\n\t"
+			 "J .+0 \n\t"
+	      :
+	      :	 "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
+			 "a" (BUF_HWCB),
+			 "a" (&(hwc_data.hwcb_count))
+	      :	 "1", "2", "3", "4", "5");
+	}
 #endif
 
 	if (hwcb->response_code == 0x0020) {
 
 		retval = OUT_HWCB_CHAR;
 		release_write_hwcb ();
-	} else
+	} else {
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "write_event_data_2 : "
+				       "failed operation "
+				       "(response code: 0x%x "
+				       "HWCB address: 0x%x).\n",
+				       hwcb->response_code,
+				       hwcb);
 		retval = -EIO;
+	}
 
 	hwc_data.current_servc = 0;
 	hwc_data.current_hwcb = NULL;
 
-	if (hwc_data.flags & FLUSH_HWCBS)
+	if (hwc_data.flags & HWC_FLUSH)
 		flush_hwcbs ();
 
 	return retval;
@@ -795,10 +805,10 @@
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		if (add_mto (message, count) != count)
 			__asm__ ("LHI 1,0xe32\n\t"
-				 "LRA 2,0(0,%0)\n\t"
-				 "L 3,0(0,%1)\n\t"
-				 "LRA 4,0(0,%2)\n\t"
-				 "LRA 5,0(0,%3)\n\t"
+				 "LRA 2,0(%0)\n\t"
+				 "L 3,0(%1)\n\t"
+				 "LRA 4,0(%2)\n\t"
+				 "LRA 5,0(%3)\n\t"
 				 "J .+0 \n\t"
 		      :
 		      :	 "a" (message), "a" (&hwc_data.kmem_pages),
@@ -864,13 +874,12 @@
 		     int from_user,
 		     unsigned char *msg,
 		     unsigned int count,
-		     unsigned char code,
 		     unsigned char write_time)
 {
 	unsigned int i_msg = 0;
 	unsigned short int spaces = 0;
 	unsigned int processed_characters = 0;
-	unsigned char ch, orig_ch;
+	unsigned char ch;
 	unsigned short int obuf_count;
 	unsigned short int obuf_cursor;
 	unsigned short int obuf_columns;
@@ -887,15 +896,10 @@
 	}
 
 	for (i_msg = 0; i_msg < count; i_msg++) {
-
 		if (from_user)
-			get_user (orig_ch, msg + i_msg);
-		else
-			orig_ch = msg[i_msg];
-		if (code == CODE_EBCDIC)
-			ch = _ebcasc[orig_ch];
+			get_user (ch, msg + i_msg);
 		else
-			ch = orig_ch;
+			ch = msg[i_msg];
 
 		processed_characters++;
 
@@ -981,8 +985,9 @@
 			if (isprint (ch))
 				hwc_data.obuf[hwc_data.obuf_start +
 					      obuf_cursor++]
-				    = (code == CODE_ASCII) ?
-				    _ascebc[orig_ch] : orig_ch;
+				    = (MACHINE_IS_VM) ?
+				    _ascebc[ch] :
+				    _ascebc_500[ch];
 		}
 		if (obuf_cursor > obuf_count)
 			obuf_count = obuf_cursor;
@@ -1044,8 +1049,8 @@
 
 	spin_lock_irqsave (&hwc_data.lock, flags);
 
-	retval = do_hwc_write (from_user, msg, count, hwc_data.ioctls.code,
-			       IMMEDIATE_WRITE);
+	retval = do_hwc_write (from_user, (unsigned char *) msg,
+			       count, IMMEDIATE_WRITE);
 
 	spin_unlock_irqrestore (&hwc_data.lock, flags);
 
@@ -1125,7 +1130,7 @@
 		if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
 			flush_hwcbs ();
 		else
-			hwc_data.flags |= FLUSH_HWCBS;
+			hwc_data.flags |= HWC_FLUSH;
 	}
 	if (flag & IN_WRITE_BUF) {
 		hwc_data.obuf_cursor = 0;
@@ -1301,13 +1306,17 @@
 	if (hwc_data.ioctls.delim)
 		count = seperate_cases (start, count);
 
-	if (hwc_data.ioctls.echo)
-		do_hwc_write (0, start, count, CODE_EBCDIC, IMMEDIATE_WRITE);
-
-	if (hwc_data.ioctls.code == CODE_ASCII)
+	if (MACHINE_IS_VM)
 		EBCASC (start, count);
+	else
+		EBCASC_500 (start, count);
 
-	store_hwc_input (start, count);
+	if (hwc_data.ioctls.echo) {
+		do_hwc_write (0, start, count, IMMEDIATE_WRITE);
+	}
+	if (hwc_data.calls != NULL)
+		if (hwc_data.calls->move_input != NULL)
+			(hwc_data.calls->move_input) (start, count);
 
 	return count;
 }
@@ -1496,8 +1505,8 @@
 #ifdef DUMP_HWC_READ_ERROR
 	if (condition_code == HWC_NOT_OPERATIONAL)
 		__asm__ ("LHI 1,0xe40\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (hwc_data.page)
@@ -1531,8 +1540,8 @@
 	    (hwcb->response_code != 0x60F0) &&
 	    (hwcb->response_code != 0x62F0))
 		__asm__ ("LHI 1,0xe41\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "L 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "L 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (hwc_data.page), "a" (&(hwcb->response_code))
@@ -1552,6 +1561,13 @@
 
 	case 0x60F0:
 	case 0x62F0:
+		internal_print (
+				       IMMEDIATE_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "unconditional read: "
+				     "got interrupt and tried to read input, "
+				  "but nothing found (response code=0x%x).\n",
+				       hwcb->response_code);
 		return 0;
 
 	case 0x0100:
@@ -1625,16 +1641,14 @@
 	unsigned int condition_code;
 	int retval;
 
-	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
-
 	condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);
 
 #ifdef DUMP_HWC_INIT_ERROR
 
-	if (condition_code != HWC_COMMAND_INITIATED)
+	if (condition_code == HWC_NOT_OPERATIONAL)
 		__asm__ ("LHI 1,0xe10\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (hwc_data.page)
@@ -1669,28 +1683,34 @@
 	if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask)
 		hwc_data.write_prio = 1;
 
-	if (hwcb->hwc_send_mask & ET_OpCmd_Mask)
+	if (hwcb->hwc_send_mask & ET_OpCmd_Mask) {
+		internal_print (DELAYED_WRITE,
+				HWC_RW_PRINT_HEADER
+				"capable of receipt of commands\n");
 		hwc_data.read_nonprio = 1;
-
-	if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask)
+	}
+	if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask) {
+		internal_print (DELAYED_WRITE,
+				HWC_RW_PRINT_HEADER
+				"capable of receipt of priority commands\n");
 		hwc_data.read_nonprio = 1;
-
+	}
 	if ((hwcb->response_code != 0x0020) ||
 	    (!hwc_data.write_nonprio) ||
 	    ((!hwc_data.read_nonprio) && (!hwc_data.read_prio)))
 #ifdef DUMP_HWC_INIT_ERROR
 		__asm__ ("LHI 1,0xe11\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "L 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "L 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (hwcb), "a" (&(hwcb->response_code))
 	      :	 "1", "2", "3");
 #else
-		retval = -EIO
+		retval = -EIO;
 #endif
 
-		    hwc_data.current_servc = 0;
+	hwc_data.current_servc = 0;
 	hwc_data.current_hwcb = NULL;
 
 	return retval;
@@ -1720,18 +1740,6 @@
 	} else
 		tmp.columns = ioctls->columns;
 
-	switch (ioctls->code) {
-	case CODE_EBCDIC:
-	case CODE_ASCII:
-		tmp.code = ioctls->code;
-		break;
-	default:
-		if (correct)
-			tmp.code = CODE_ASCII;
-		else
-			retval = -EINVAL;
-	}
-
 	tmp.final_nl = ioctls->final_nl;
 
 	if (ioctls->max_hwcb < 2) {
@@ -1773,9 +1781,55 @@
 }
 
 int 
+do_hwc_init (void)
+{
+	int retval;
+
+	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
+
+	do {
+
+		retval = write_event_mask_1 ();
+
+		if (retval == -EBUSY) {
+
+			hwc_data.flags |= HWC_INIT;
+
+			__ctl_store (cr0, 0, 0);
+			cr0_save = cr0;
+			cr0 |= 0x00000200;
+			cr0 &= 0xFFFFF3AC;
+			__ctl_load (cr0, 0, 0);
+
+			asm volatile ("STOSM %0,0x01"
+				      :"=m" (psw_mask)::"memory");
+
+			while (!(hwc_data.flags & HWC_INTERRUPT))
+				barrier ();
+
+			asm volatile ("STNSM %0,0xFE"
+				      :"=m" (psw_mask)::"memory");
+
+			__ctl_load (cr0_save, 0, 0);
+
+			hwc_data.flags &= ~HWC_INIT;
+		}
+	} while (retval == -EBUSY);
+
+	if (retval == -EIO) {
+		hwc_data.flags |= HWC_BROKEN;
+		printk (HWC_RW_PRINT_HEADER "HWC not operational\n");
+	}
+	return retval;
+}
+
+void do_hwc_interrupt (struct pt_regs *regs, __u16 code);
+
+int 
 hwc_init (void)
 {
 	int retval;
+
 #ifdef BUFFER_STRESS_TEST
 
 	init_hwcb_t *hwcb;
@@ -1783,17 +1837,11 @@
 
 #endif
 
-#ifdef CONFIG_3215
-	if (MACHINE_IS_VM)
-		return 0;
-#endif
+	if (register_external_interrupt (0x2401, do_hwc_interrupt) != 0)
+		panic ("Couldn't request external interrupts 0x2401");
 
 	spin_lock_init (&hwc_data.lock);
 
-	retval = write_event_mask_1 ();
-	if (retval < 0)
-		return retval;
-
 #ifdef USE_VM_DETECTION
 
 	if (MACHINE_IS_VM) {
@@ -1811,10 +1859,12 @@
 	retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
 
 	hwc_data.kmem_start = (unsigned long)
-	    alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
+	    alloc_bootmem_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
 	hwc_data.kmem_end = hwc_data.kmem_start +
 	    hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;
 
+	retval = do_hwc_init ();
+
 	ctl_set_bit (0, 9);
 
 #ifdef BUFFER_STRESS_TEST
@@ -1836,45 +1886,108 @@
 
 #endif
 
-	return retval;
+	return /*retval */ 0;
 }
 
-void 
-do_hwc_interrupt (void)
+signed int 
+hwc_register_calls (hwc_high_level_calls_t * calls)
 {
+	if (calls == NULL)
+		return -EINVAL;
 
-	spin_lock (&hwc_data.lock);
+	if (hwc_data.calls != NULL)
+		return -EBUSY;
 
-	if (!hwc_data.current_servc) {
+	hwc_data.calls = calls;
+	return 0;
+}
 
-		unconditional_read_1 ();
+signed int 
+hwc_unregister_calls (hwc_high_level_calls_t * calls)
+{
+	if (hwc_data.calls == NULL)
+		return -EINVAL;
+
+	if (calls != hwc_data.calls)
+		return -EINVAL;
+
+	hwc_data.calls = NULL;
+	return 0;
+}
 
+void 
+do_hwc_interrupt (struct pt_regs *regs, __u16 code)
+{
+
+	if (hwc_data.flags & HWC_INIT) {
+
+		hwc_data.flags |= HWC_INTERRUPT;
+	} else if (hwc_data.flags & HWC_BROKEN) {
+
+		if (!do_hwc_init ()) {
+			hwc_data.flags &= ~HWC_BROKEN;
+			internal_print (DELAYED_WRITE,
+					HWC_RW_PRINT_HEADER
+					"delayed HWC setup after"
+					" temporary breakdown\n");
+		}
 	} else {
+		spin_lock (&hwc_data.lock);
 
-		switch (hwc_data.current_servc) {
+		if (!hwc_data.current_servc) {
 
-		case HWC_CMDW_WRITEMASK:
+			unconditional_read_1 ();
 
-			write_event_mask_2 ();
-			break;
+		} else {
 
-		case HWC_CMDW_WRITEDATA:
+			switch (hwc_data.current_servc) {
 
-			write_event_data_2 ();
-			break;
+			case HWC_CMDW_WRITEMASK:
 
-		case HWC_CMDW_READDATA:
+				write_event_mask_2 ();
+				break;
 
-			unconditional_read_2 ();
-			break;
-		}
+			case HWC_CMDW_WRITEDATA:
 
-		write_event_data_1 ();
+				write_event_data_2 ();
+				break;
+
+			case HWC_CMDW_READDATA:
+
+				unconditional_read_2 ();
+				break;
+			}
+
+			write_event_data_1 ();
+		}
+		if (hwc_data.calls != NULL)
+			if (hwc_data.calls->wake_up != NULL)
+				(hwc_data.calls->wake_up) ();
+		spin_unlock (&hwc_data.lock);
 	}
+}
 
-	wake_up_hwc_tty ();
+void 
+hwc_unblank (void)
+{
 
+	spin_lock (&hwc_data.lock);
 	spin_unlock (&hwc_data.lock);
+
+	__ctl_store (cr0, 0, 0);
+	cr0_save = cr0;
+	cr0 |= 0x00000200;
+	cr0 &= 0xFFFFF3AC;
+	__ctl_load (cr0, 0, 0);
+
+	asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");
+
+	while (ALL_HWCB_CHAR)
+		barrier ();
+
+	asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");
+
+	__ctl_load (cr0_save, 0, 0);
 }
 
 int 
@@ -1904,12 +2017,6 @@
 			goto fault;
 		break;
 
-	case TIOCHWCSCODE:
-		if (get_user (tmp.code, (ioctl_code_t *) arg))
-			goto fault;
-
-		break;
-
 	case TIOCHWCSNL:
 		if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))
 			goto fault;
@@ -1951,12 +2058,6 @@
 	case TIOCHWCGCOLS:
 		if (put_user (tmp.columns, (ioctl_cols_t *) arg))
 			goto fault;
-		break;
-
-	case TIOCHWCGCODE:
-		if (put_user (tmp.code, (ioctl_code_t *) arg))
-			goto fault;
-
 		break;
 
 	case TIOCHWCGNL:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)