Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Handle (i.e. don't lock up the kernel in hd44780_...



details:   https://anonhg.NetBSD.org/src/rev/8a0afde0fe9c
branches:  trunk
changeset: 572633:8a0afde0fe9c
user:      joff <joff%NetBSD.org@localhost>
date:      Sun Jan 09 15:43:56 2005 +0000

description:
Handle (i.e. don't lock up the kernel in hd44780_busy_wait) the case of the
LCD not being there.

diffstat:

 sys/dev/ic/hd44780_subr.c |  84 ++++++++++++++++++++++++++++++++++++----------
 sys/dev/ic/hd44780_subr.h |   8 ++--
 2 files changed, 70 insertions(+), 22 deletions(-)

diffs (222 lines):

diff -r e917739bc0c7 -r 8a0afde0fe9c sys/dev/ic/hd44780_subr.c
--- a/sys/dev/ic/hd44780_subr.c Sun Jan 09 15:39:59 2005 +0000
+++ b/sys/dev/ic/hd44780_subr.c Sun Jan 09 15:43:56 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hd44780_subr.c,v 1.2 2005/01/08 20:17:22 joff Exp $ */
+/* $NetBSD: hd44780_subr.c,v 1.3 2005/01/09 15:43:56 joff Exp $ */
 
 /*
  * Copyright (c) 2002 Dennis I. Chernoivanov
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hd44780_subr.c,v 1.2 2005/01/08 20:17:22 joff Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hd44780_subr.c,v 1.3 2005/01/09 15:43:56 joff Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -48,8 +48,6 @@
 #include <dev/ic/hd44780reg.h>
 #include <dev/ic/hd44780_subr.h>
 
-static void    hd44780_init(struct hd44780_chip *);
-
 /*
  * Finish device attach. sc_writereg, sc_readreg and sc_flags must be properly
  * initialized prior to this call.
@@ -58,6 +56,7 @@
 hd44780_attach_subr(sc)
        struct hd44780_chip *sc;
 {
+       int err = 0;
        /* Putc/getc are supposed to be set by platform-dependent code. */
        if ((sc->sc_writereg == NULL) || (sc->sc_readreg == NULL))
                sc->sc_dev_ok = 0;
@@ -69,24 +68,25 @@
                sc->sc_dev_ok = 0;
 
        if (sc->sc_dev_ok) {
-               if ((sc->sc_flags & HD_UP) == 0)
-                       hd44780_init(sc);
+               if ((sc->sc_flags & HD_UP) == 0) 
+                       err = hd44780_init(sc);
+               if (err != 0)
+                       printf("%s: not responding or unconnected\n", sc->sc_dev->dv_xname);
 
-               /* Turn display on and clear it. */
-               hd44780_ir_write(sc, cmd_dispctl(1, 0, 0));
-               hd44780_ir_write(sc, cmd_clear());
        }
 }
 
 /*
  * Initialize 4-bit or 8-bit connected device.
  */
-static void
+int
 hd44780_init(sc)
        struct hd44780_chip *sc;
 {
-       u_int8_t cmd;
+       u_int8_t cmd, dat;
 
+       sc->sc_flags &= ~(HD_TIMEDOUT|HD_UP);
+       sc->sc_dev_ok = 1;
        cmd = cmd_init(sc->sc_flags & HD_8BIT);
        hd44780_ir_write(sc, cmd);
        delay(HD_TIMEOUT_LONG);
@@ -107,6 +107,28 @@
        hd44780_ir_write(sc, cmd_dispctl(0, 0, 0));
        hd44780_ir_write(sc, cmd_clear());
        hd44780_ir_write(sc, cmd_modset(1, 0));
+
+       if (sc->sc_flags & HD_TIMEDOUT) {
+               sc->sc_flags &= ~HD_UP;
+               return EIO;
+       } 
+
+       /* Turn display on and clear it. */
+       hd44780_ir_write(sc, cmd_clear());
+       hd44780_ir_write(sc, cmd_dispctl(1, 0, 0));
+
+       /* Attempt a simple probe for presence */
+       hd44780_ir_write(sc, cmd_ddramset(0x5));
+       hd44780_ir_write(sc, cmd_shift(0, 1));
+       hd44780_busy_wait(sc);
+       if ((dat = hd44780_ir_read(sc) & 0x7f) != 0x6) {
+               sc->sc_dev_ok = 0;
+               sc->sc_flags &= ~HD_UP;
+               return EIO;
+       }
+       hd44780_ir_write(sc, cmd_ddramset(0));
+
+       return 0;
 }
 
 /*
@@ -163,13 +185,7 @@
 
                /* Reset the LCD. */
                case HLCD_RESET:
-                       hd44780_ir_write(sc, cmd_init(sc->sc_flags & HD_8BIT));
-                       hd44780_ir_write(sc, cmd_init(sc->sc_flags & HD_8BIT));
-                       hd44780_ir_write(sc, cmd_init(sc->sc_flags & HD_8BIT));
-                       hd44780_ir_write(sc, cmd_init(sc->sc_flags & HD_8BIT));
-                       hd44780_ir_write(sc, cmd_modset(1, 0));
-                       hd44780_ir_write(sc, cmd_dispctl(1, 0, 0));
-                       hd44780_ir_write(sc, cmd_clear());
+                       error = hd44780_init(sc);
                        break;
 
                /* Get the current cursor position. */
@@ -238,6 +254,9 @@
                        error = EINVAL;
        }
 
+       if (sc->sc_flags & HD_TIMEDOUT)
+               error = EIO;
+
        return error;
 }
 
@@ -308,6 +327,23 @@
                hd44780_dr_write(sc, io->buf[i]);
 }
 
+void
+hd44780_busy_wait(sc)
+       struct hd44780_chip *sc;
+{
+       int nloops = 100;
+
+       if (sc->sc_flags & HD_TIMEDOUT)
+               return;
+
+       while(nloops-- && (hd44780_ir_read(sc) & BUSY_FLAG) == BUSY_FLAG);
+
+       if (nloops == 0) {
+               sc->sc_flags |= HD_TIMEDOUT;
+               sc->sc_dev_ok = 0;
+       }
+}
+
 #if defined(HD44780_STD_WIDE)
 /*
  * Standard 8-bit version of 'sc_writereg' (8-bit port, 8-bit access)
@@ -321,6 +357,9 @@
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh;
 
+       if (sc->sc_dev_ok == 0)
+               return;
+
        if (reg == 0)
                ioh = sc->sc_ioir; 
        else
@@ -341,6 +380,9 @@
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh;
 
+       if (sc->sc_dev_ok == 0)
+               return;
+
        if (reg == 0)
                ioh = sc->sc_ioir; 
        else
@@ -362,6 +404,9 @@
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh;
 
+       if (sc->sc_dev_ok == 0)
+               return;
+
        if (reg == 0)
                ioh = sc->sc_ioir; 
        else
@@ -385,6 +430,9 @@
        bus_space_handle_t ioh;
        u_int8_t rd, dat;
 
+       if (sc->sc_dev_ok == 0)
+               return;
+
        if (reg == 0)
                ioh = sc->sc_ioir; 
        else
diff -r e917739bc0c7 -r 8a0afde0fe9c sys/dev/ic/hd44780_subr.h
--- a/sys/dev/ic/hd44780_subr.h Sun Jan 09 15:39:59 2005 +0000
+++ b/sys/dev/ic/hd44780_subr.h Sun Jan 09 15:43:56 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hd44780_subr.h,v 1.2 2005/01/08 20:17:22 joff Exp $ */
+/* $NetBSD: hd44780_subr.h,v 1.3 2005/01/09 15:43:56 joff Exp $ */
 
 /*
  * Copyright (c) 2002 Dennis I. Chernoivanov
@@ -81,6 +81,7 @@
 #define HD_BIGFONT             0x04    /* 5x10 if set, 5x8 otherwise */
 #define HD_KEYPAD              0x08    /* if set, keypad is connected */
 #define HD_UP                  0x10    /* if set, lcd has been initialized */
+#define HD_TIMEDOUT            0x20    /* lcd has recently stopped talking */
        u_char sc_flags;
 
        u_char sc_rows;                 /* visible rows */
@@ -99,9 +100,6 @@
        u_int8_t (* sc_readreg)(struct hd44780_chip *, u_int32_t);
 };
 
-#define hd44780_busy_wait(sc) \
-       while((hd44780_ir_read(sc) & BUSY_FLAG) == BUSY_FLAG)
-
 #define hd44780_ir_write(sc, dat) \
        do {                                                            \
                hd44780_busy_wait(sc);                                  \
@@ -118,6 +116,8 @@
        (sc)->sc_readreg((sc), 1)
 
 void hd44780_attach_subr(struct hd44780_chip *);
+void hd44780_busy_wait(struct hd44780_chip *);
+int  hd44780_init(struct hd44780_chip *);
 int  hd44780_ioctl_subr(struct hd44780_chip *, u_long, caddr_t);
 void hd44780_ddram_redraw(struct hd44780_chip *, struct hd44780_io *);
 



Home | Main Index | Thread Index | Old Index