Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Make console polling (cnpollc/cngetc) work on IBM PS/2 k...



details:   https://anonhg.NetBSD.org/src/rev/7f56fa068851
branches:  trunk
changeset: 513437:7f56fa068851
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Tue Jul 31 13:15:28 2001 +0000

description:
Make console polling (cnpollc/cngetc) work on IBM PS/2 keyboard controller
using level triggered interrupts, which livelocks calling intr routine
if the data register is not read in the interrupt routine, as it's case
when polling after interrupts are enabled during boot.

Block all interrupts when polling for keypress, and modify intr routine
to read and store value from data register. The latter one is to avoid
losing a keypress when one would manage to press a key when kernel is
not in spl-guarded code section.

Tested with classic pccons, 'pcconskbd at pckbc' and 'pckbd at pckbc'
configurations, on i386.

diffstat:

 sys/arch/i386/isa/pccons.c |  30 ++++++++++++++++++++++++++----
 sys/dev/ic/pckbc.c         |  43 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 62 insertions(+), 11 deletions(-)

diffs (187 lines):

diff -r 95556a5abd42 -r 7f56fa068851 sys/arch/i386/isa/pccons.c
--- a/sys/arch/i386/isa/pccons.c        Tue Jul 31 12:33:11 2001 +0000
+++ b/sys/arch/i386/isa/pccons.c        Tue Jul 31 13:15:28 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pccons.c,v 1.148 2001/07/24 22:29:08 wiz Exp $ */
+/*     $NetBSD: pccons.c,v 1.149 2001/07/31 13:15:29 jdolecek Exp $    */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -157,6 +157,7 @@
 static u_short *crtat;                 /* pointer to current char */
 #if (NPCCONSKBD == 0)
 static volatile u_char ack, nak;       /* Don't ask. */
+static int poll_data = -1;
 #endif
 static u_char async, kernel, polling;  /* Really, you don't want to know. */
 static u_char lock_state = 0x00;       /* all off */
@@ -942,10 +943,13 @@
 
        if ((inb(IO_KBD + KBSTATP) & KBS_DIB) == 0)
                return (0);
-       if (polling)
-               return (1);
        do {
                cp = sget();
+
+               if (polling) {
+                       poll_data = *cp;
+                       return (1);
+               }
                if (!tp || (tp->t_state & TS_ISOPEN) == 0)
                        return (1);
                if (cp)
@@ -1119,6 +1123,11 @@
        kernel = oldkernel;
 }
 
+/*
+ * Note: the spl games here are to deal with some strange PC kbd controllers
+ * in some system configurations.
+ * This is not canonical way to handle polling input.
+ */
 /* ARGSUSED */
 int
 pccngetc(dev)
@@ -1134,9 +1143,20 @@
        do {
                /* wait for byte */
 #if (NPCCONSKBD == 0)
+               int s = splhigh();
+
+               if (poll_data != -1) {
+                       int data = poll_data;
+                       poll_data = -1;
+                       splx(s);
+                       return (data);
+               }
+
                while ((inb(IO_KBD + KBSTATP) & KBS_DIB) == 0);
+
                /* see if it's worthwhile */
                cp = sget();
+               splx(s);
 #else
                int data;
                do {
@@ -1160,7 +1180,9 @@
 #if (NPCCONSKBD > 0)
        pckbc_set_poll(kbctag, kbcslot, on);
 #else
-       if (!on) {
+       if (on)
+               poll_data = -1;
+       else {
                int unit;
                struct pc_softc *sc;
                int s;
diff -r 95556a5abd42 -r 7f56fa068851 sys/dev/ic/pckbc.c
--- a/sys/dev/ic/pckbc.c        Tue Jul 31 12:33:11 2001 +0000
+++ b/sys/dev/ic/pckbc.c        Tue Jul 31 13:15:28 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pckbc.c,v 1.14 2001/07/23 21:03:21 jdolecek Exp $ */
+/* $NetBSD: pckbc.c,v 1.15 2001/07/31 13:15:28 jdolecek Exp $ */
 
 /*
  * Copyright (c) 1998
@@ -76,7 +76,9 @@
 
 /* data per slave device */
 struct pckbc_slotdata {
-       int polling; /* don't read data port in interrupt handler */
+       int polling;    /* don't process data in interrupt handler */
+       int poll_data;  /* data read from inr handler if polling */
+       int poll_stat;  /* status read from inr handler if polling */
        TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* active commands */
        TAILQ_HEAD(, pckbc_devcmd) freequeue; /* free commands */
 #define NCMD 5
@@ -147,6 +149,11 @@
        return (1);
 }
 
+/*
+ * Note: the spl games here are to deal with some strange PC kbd controllers
+ * in some system configurations.
+ * This is not canonical way to handle polling input.
+ */
 int
 pckbc_poll_data1(pt, slot, checkaux)
        pckbc_tag_t pt;
@@ -154,9 +161,20 @@
        int checkaux;
 {
        struct pckbc_internal *t = pt;
-       int i;
+       struct pckbc_slotdata *q = t->t_slotdata[slot];
+       int i, s;
        u_char stat, c;
 
+       s = splhigh();
+
+       if (q && q->polling && q->poll_data != -1 && q->poll_stat != -1) {
+               stat    = q->poll_stat;
+               c       = q->poll_data;
+               q->poll_data = -1;
+               q->poll_stat = -1;
+               goto process;
+       }
+
        /* if 1 port read takes 1us (?), this polls for 100ms */
        for (i = 100000; i; i--) {
                stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0);
@@ -164,6 +182,7 @@
                        KBD_DELAY;
                        c = bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
                    
+                   process:
                        if (checkaux && (stat & 0x20)) { /* aux data */
                                if (slot != PCKBC_AUX_SLOT) {
 #ifdef PCKBCDEBUG
@@ -179,9 +198,12 @@
                                        continue;
                                }
                        }
+                       splx(s);
                        return (c);
                }
        }
+
+       splx(s);
        return (-1);
 }
 
@@ -522,7 +544,10 @@
 
        t->t_slotdata[slot]->polling = on;
 
-       if (!on) {
+       if (on) {
+               t->t_slotdata[slot]->poll_data = -1;
+               t->t_slotdata[slot]->poll_stat = -1;
+       } else {
                 int s;
 
                 /*
@@ -917,15 +942,19 @@
                        continue;
                }
 
-               if (q->polling)
-                       break; /* pckbc_poll_data() will get it */
-
                KBD_DELAY;
                data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
 
 #if NRND > 0
                rnd_add_uint32(&q->rnd_source, (stat<<8)|data);
 #endif
+
+               if (q->polling) {
+                       q->poll_data = data;
+                       q->poll_stat = stat;
+                       break; /* pckbc_poll_data() will get it */
+               }
+
                if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data))
                        continue;
 



Home | Main Index | Thread Index | Old Index