From e71440687f5b1c58a440fcaf07738d06e7705fa5 Mon Sep 17 00:00:00 2001
From: Michael Shalayeff <mickey@cvs.openbsd.org>
Date: Thu, 29 Oct 1998 17:47:16 +0000
Subject: fix pdccngetc() input handling

---
 sys/arch/hppa/dev/pdc.c | 79 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 57 insertions(+), 22 deletions(-)

(limited to 'sys')

diff --git a/sys/arch/hppa/dev/pdc.c b/sys/arch/hppa/dev/pdc.c
index 1f425ed2766..3ae34033a8a 100644
--- a/sys/arch/hppa/dev/pdc.c
+++ b/sys/arch/hppa/dev/pdc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pdc.c,v 1.2 1998/09/14 18:59:49 mickey Exp $	*/
+/*	$OpenBSD: pdc.c,v 1.3 1998/10/29 17:47:15 mickey Exp $	*/
 
 /*
  * Copyright (c) 1998 Michael Shalayeff
@@ -42,10 +42,10 @@
 
 #include <dev/cons.h>
 
-#include <machine/autoconf.h>
 #include <machine/conf.h>
 #include <machine/pdc.h>
 #include <machine/iomod.h>
+#include <machine/autoconf.h>
 
 typedef
 struct pdc_softc {
@@ -73,13 +73,29 @@ struct cfdriver pdc_cd = {
 void
 pdc_init()
 {
+	static int kbd_iodc[IODC_MAXSIZE/sizeof(int)];
+	static int cn_iodc[IODC_MAXSIZE/sizeof(int)];
+	int err;
+
 	/* XXX locore've done it XXX pdc = (pdcio_t)PAGE0->mem_pdc; */
 	pz_kbd = &PAGE0->mem_kbd;
 	pz_cons = &PAGE0->mem_cons;
 
-	/* following the memory mappings, console iodc is at `mem_free' */
-	pdc_cniodc = (iodcio_t)PAGE0->mem_free;
-	pdc_kbdiodc = (iodcio_t)PAGE0->mem_free;
+	/* XXX should we reset the console/kbd here?
+	   well, /boot did that for us anyway */
+	if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ,
+			    pdcret, pz_cons->pz_hpa,
+			    IODC_IO, cn_iodc, IODC_MAXSIZE)) < 0 ||
+	    (err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ,
+			    pdcret, pz_kbd->pz_hpa,
+			    IODC_IO, kbd_iodc, IODC_MAXSIZE)) < 0) {
+#ifdef DEBUG
+		printf("pdc_init: failed reading IODC (%d)\n", err);
+#endif
+	}
+
+	pdc_cniodc = (iodcio_t)cn_iodc;
+	pdc_kbdiodc = (iodcio_t)kbd_iodc;
 
 	/* XXX make pdc current console */
 	cn_tab = &constab[0];
@@ -91,11 +107,11 @@ pdcmatch(parent, cfdata, aux)
 	void *cfdata;
 	void *aux;
 {
-	/* struct cfdata *cf = cfdata; */
+	struct cfdata *cf = cfdata;
 	struct confargs *ca = aux;
 
 	/* there could be only one */
-	if (pdc_cd.cd_ndevs || strcmp(ca->ca_name, pdc_cd.cd_name))
+	if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "pdc"))
 		return 0;
 
 	return 1;
@@ -107,9 +123,10 @@ pdcattach(parent, self, aux)
 	struct device *self;
 	void *aux;
 {
-	printf("\n");
 	if (!pdc)
 		pdc_init();
+
+	printf("\n");
 }
 
 int
@@ -226,33 +243,51 @@ void
 pdccninit(cn)
 	struct consdev *cn;
 {
-
+#ifdef DEBUG
+	printf("pdc0: console init\n");
+#endif
 }
 
 int
 pdccngetc(dev)
 	dev_t dev;
 {
-	int err;
+	static int stash = 0;
+	register int err, c, l;
 
 	if (!pdc)
 		return 0;
 
-	if ((err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, IODC_IO_CONSIN,
-			    &pz_kbd->pz_spa, pz_kbd->pz_layers, pdcret,
-			    0, pdc_consbuf, 1, 0)) < 0) {
-#ifdef DEBUG
-		printf("pdc_getc: input error: %d\n", err);
-#endif
+	if (stash) {
+		c = stash;
+		if (!(dev & 0x80))
+			stash = 0;
+		return c;
 	}
 
-	if (pdcret[0] == 0)
-		return (0);
+	do {
+		err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa,
+			       IODC_IO_CONSIN, pz_kbd->pz_spa,
+			       pz_kbd->pz_layers, pdcret,
+			       0, pdc_consbuf, 1, 0);
+
+		l = pdcret[0];
+		c = pdc_consbuf[0];
 #ifdef DEBUG
-	if (pdcret[0] > 1)
-		printf("pdc_getc: input got too much (%d)\n", pdcret[0]);
+		if (err < 0)
+			printf("pdccngetc: input error: %d\n", err);
 #endif
-	return *pdc_consbuf;
+
+		/* if we are doing ischar() report immidiatelly */
+		if (dev & 0x80 && l == 0)
+			return (0);
+
+	} while(!l);
+
+	if (dev & 0x80)
+		stash = c;
+
+	return (c);
 }
 
 void
@@ -267,7 +302,7 @@ pdccnputc(dev, c)
 			    pz_cons->pz_spa, pz_cons->pz_layers,
 			    pdcret, 0, pdc_consbuf, 1, 0)) < 0) {
 #ifdef DEBUG
-		printf("pdc_putc: output error: %d\n", err);
+		printf("pdccnputc: output error: %d\n", err);
 #endif
 	}
 
-- 
cgit v1.2.3