summaryrefslogtreecommitdiffstats
path: root/sys/dev/sab
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2002-11-17 16:00:51 +0000
committerjake <jake@FreeBSD.org>2002-11-17 16:00:51 +0000
commit67c42884ec9d00482ca7756923cbb22be064c52e (patch)
tree1bdde3a7f2ab0bb2680d5f58688264c28240b443 /sys/dev/sab
parent2a39e4d9df913f6df8c8074d40b3c44468abd424 (diff)
downloadFreeBSD-src-67c42884ec9d00482ca7756923cbb22be064c52e.zip
FreeBSD-src-67c42884ec9d00482ca7756923cbb22be064c52e.tar.gz
- Add support for ALT_BREAK_TO_DEBUGGER; this is the only reliable way to
trigger a breakpoint with this chip. - Fiddle the right bits in the cn input and output routines to disable port interrupts and enable visibility of the masked interrupt status bits. - Register a shutdown final event handler to put the chip back in the mode that the prom expects.
Diffstat (limited to 'sys/dev/sab')
-rw-r--r--sys/dev/sab/sab.c124
1 files changed, 103 insertions, 21 deletions
diff --git a/sys/dev/sab/sab.c b/sys/dev/sab/sab.c
index 9502dd5..85fe9ab 100644
--- a/sys/dev/sab/sab.c
+++ b/sys/dev/sab/sab.c
@@ -83,6 +83,7 @@
struct sabtty_softc {
device_t sc_dev;
+ struct sab_softc *sc_parent;
bus_space_tag_t sc_bt;
bus_space_handle_t sc_bh;
dev_t sc_si;
@@ -122,6 +123,7 @@ struct sab_softc {
int sc_irqrid;
struct resource *sc_iores;
int sc_iorid;
+ uint8_t sc_ipc;
};
static int sab_probe(device_t dev);
@@ -130,6 +132,7 @@ static int sab_detach(device_t dev);
static void sab_intr(void *vsc);
static void sab_softintr(void *vsc);
+static void sab_shutdown(void *vsc);
static int sabtty_probe(device_t dev);
static int sabtty_attach(device_t dev);
@@ -328,18 +331,20 @@ sab_attach(device_t dev)
sc->sc_irqrid = irqrid;
sc->sc_bt = rman_get_bustag(iores);
sc->sc_bh = rman_get_bushandle(iores);
- for (i = 0; i < SAB_NCHAN; i++)
- child[i] = device_add_child(dev, "sabtty", i);
- bus_generic_attach(dev);
- for (i = 0; i < SAB_NCHAN; i++)
- sc->sc_child[i] = device_get_softc(child[i]);
/* Set all pins, except DTR pins to be inputs */
SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B));
/* Disable port interrupts */
SAB_WRITE(sc, SAB_PIM, 0xff);
SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC);
- SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL);
+ sc->sc_ipc = SAB_IPC_ICPL | SAB_IPC_VIS;
+ SAB_WRITE(sc, SAB_IPC, sc->sc_ipc);
+
+ for (i = 0; i < SAB_NCHAN; i++)
+ child[i] = device_add_child(dev, "sabtty", i);
+ bus_generic_attach(dev);
+ for (i = 0; i < SAB_NCHAN; i++)
+ sc->sc_child[i] = device_get_softc(child[i]);
swi_add(&tty_ithd, "tty:sab", sab_softintr, sc, SWI_TTY,
INTR_TYPE_TTY, &sc->sc_softih);
@@ -350,6 +355,9 @@ sab_attach(device_t dev)
sabtty_cons->sc_tty->t_ospeed);
}
+ EVENTHANDLER_REGISTER(shutdown_final, sab_shutdown, sc,
+ SHUTDOWN_PRI_DEFAULT);
+
return (0);
error:
@@ -403,6 +411,15 @@ sab_softintr(void *vsc)
sabtty_softintr(sc->sc_child[1]);
}
+static void
+sab_shutdown(void *vsc)
+{
+ struct sab_softc *sc = vsc;
+
+ SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL | SAB_IPC_VIS);
+ SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF);
+}
+
static int
sabtty_probe(device_t dev)
{
@@ -423,7 +440,6 @@ sabtty_probe(device_t dev)
static int
sabtty_attach(device_t dev)
{
- struct sab_softc *parent;
struct sabtty_softc *sc;
struct tty *tp;
char mode[32];
@@ -436,8 +452,8 @@ sabtty_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->sc_mtx, "sabtty", NULL, MTX_SPIN);
sc->sc_dev = dev;
- parent = device_get_softc(device_get_parent(dev));
- sc->sc_bt = parent->sc_bt;
+ sc->sc_parent = device_get_softc(device_get_parent(dev));
+ sc->sc_bt = sc->sc_parent->sc_bt;
sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE;
sc->sc_xend = sc->sc_xbuf + SABTTY_XBUF_SIZE;
@@ -445,12 +461,12 @@ sabtty_attach(device_t dev)
case 0: /* port A */
sc->sc_pvr_dtr = SAB_PVR_DTR_A;
sc->sc_pvr_dsr = SAB_PVR_DSR_A;
- sc->sc_bh = parent->sc_bh + SAB_CHAN_A;
+ sc->sc_bh = sc->sc_parent->sc_bh + SAB_CHAN_A;
break;
case 1: /* port B */
sc->sc_pvr_dtr = SAB_PVR_DTR_B;
sc->sc_pvr_dsr = SAB_PVR_DSR_B;
- sc->sc_bh = parent->sc_bh + SAB_CHAN_B;
+ sc->sc_bh = sc->sc_parent->sc_bh + SAB_CHAN_B;
break;
default:
return (ENXIO);
@@ -476,6 +492,7 @@ sabtty_attach(device_t dev)
DELAY(100000);
sabtty_reset(sc);
+ ttychars(tp);
if (sscanf(mode, "%d,%d,%c,%d,%c", &baud, &clen, &parity,
&stop, &c) == 5) {
tp->t_ospeed = baud;
@@ -537,6 +554,8 @@ sabtty_intr(struct sabtty_softc *sc)
{
uint8_t isr0, isr1;
int i, len = 0, needsoft = 0, clearfifo = 0;
+ int brk = 0;
+ uint8_t data;
uint8_t *ptr;
SABTTY_LOCK(sc);
@@ -563,7 +582,41 @@ sabtty_intr(struct sabtty_softc *sc)
if (len != 0) {
ptr = sc->sc_rput;
for (i = 0; i < len; i++) {
- *ptr++ = SAB_READ(sc, SAB_RFIFO);
+ data = SAB_READ(sc, SAB_RFIFO);
+#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
+ /*
+ * Solaris implements a new BREAK which is initiated
+ * by a character sequence CR ~ ^b which is similar
+ * to a familiar pattern used on Sun servers by the
+ * Remote Console.
+ */
+#define KEY_CR 13 /* CR '\r' */
+#define KEY_TILDE 126 /* ~ */
+#define KEY_CRTLB 2 /* ^B */
+
+ if ((sc->sc_flags & SABTTYF_CONS) != 0 &&
+ (i & 1) == 0) {
+ static int state;
+ switch (data) {
+ case KEY_CR:
+ state = KEY_TILDE;
+ break;
+ case KEY_TILDE:
+ if (state == KEY_TILDE)
+ state = KEY_CRTLB;
+ else
+ state = 0;
+ break;
+ case KEY_CRTLB:
+ if (state == KEY_CRTLB)
+ brk = 1;
+ default:
+ state = 0;
+ break;
+ }
+ }
+#endif
+ *ptr++ = data;
if (ptr == sc->sc_rend)
ptr = sc->sc_rbuf;
if (ptr == sc->sc_rget) {
@@ -587,11 +640,6 @@ sabtty_intr(struct sabtty_softc *sc)
needsoft = 1;
}
-#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
- if ((isr1 & SAB_ISR1_BRKT) && (sc->sc_flags & SABTTYF_CONS))
- Debugger("break");
-#endif
-
if (isr1 & SAB_ISR1_ALLS) {
if (sc->sc_flags & SABTTYF_TXDRAIN)
wakeup(sc);
@@ -624,6 +672,12 @@ sabtty_intr(struct sabtty_softc *sc)
}
SABTTY_UNLOCK(sc);
+
+#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
+ if (brk)
+ breakpoint();
+#endif
+
return (needsoft);
}
@@ -702,6 +756,8 @@ sabttyopen(dev_t dev, int flags, int mode, struct thread *td)
sabtty_reset(sc);
sabtty_param(sc, tp, &tp->t_termios);
+ sc->sc_parent->sc_ipc = SAB_IPC_ICPL;
+ SAB_WRITE(sc->sc_parent, SAB_IPC, sc->sc_parent->sc_ipc);
sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA;
SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU |
@@ -1106,7 +1162,7 @@ sabtty_tec_wait(struct sabtty_softc *sc)
}
}
-void
+static void
sabtty_reset(struct sabtty_softc *sc)
{
/* power down */
@@ -1131,7 +1187,7 @@ sabtty_reset(struct sabtty_softc *sc)
SAB_READ(sc, SAB_ISR1);
}
-void
+static void
sabtty_flush(struct sabtty_softc *sc)
{
@@ -1221,12 +1277,31 @@ sab_cndbctl(dev_t dev, int c)
{
}
+static void
+sabtty_cnopen(struct sabtty_softc *sc)
+{
+
+ SAB_WRITE(sc, SAB_IMR0, 0xff);
+ SAB_WRITE(sc, SAB_IMR1, 0xff);
+ SAB_WRITE(sc->sc_parent, SAB_IPC, sc->sc_parent->sc_ipc | SAB_IPC_VIS);
+}
+
+static void
+sabtty_cnclose(struct sabtty_softc *sc)
+{
+
+ SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
+ SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
+ SAB_WRITE(sc->sc_parent, SAB_IPC, sc->sc_parent->sc_ipc);
+}
+
static int
sabtty_cngetc(struct sabtty_softc *sc)
{
uint8_t len;
uint8_t r;
+ sabtty_cnopen(sc);
again:
do {
r = SAB_READ(sc, SAB_STAR);
@@ -1255,25 +1330,32 @@ again:
*/
sabtty_cec_wait(sc);
SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC);
+ sabtty_cnclose(sc);
return (r);
}
static int
sabtty_cncheckc(struct sabtty_softc *sc)
{
+ int8_t r;
+ r = -1;
+ sabtty_cnopen(sc);
if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_RFNE) != 0)
- return (sabtty_cngetc(sc));
- return (-1);
+ r = sabtty_cngetc(sc);
+ sabtty_cnclose(sc);
+ return (r);
}
static void
sabtty_cnputc(struct sabtty_softc *sc, int c)
{
+ sabtty_cnopen(sc);
sabtty_tec_wait(sc);
SAB_WRITE(sc, SAB_TIC, c);
sabtty_tec_wait(sc);
+ sabtty_cnclose(sc);
}
static int
OpenPOWER on IntegriCloud