From: kettenis Date: Thu, 10 Jul 2008 20:27:36 +0000 (+0000) Subject: Handle breaks. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=84706f18dd42b61437cf0f039e846559972b3946;p=openbsd Handle breaks. --- diff --git a/sys/arch/sparc64/dev/sbbc.c b/sys/arch/sparc64/dev/sbbc.c index 092ad24c8c9..96047eda594 100644 --- a/sys/arch/sparc64/dev/sbbc.c +++ b/sys/arch/sparc64/dev/sbbc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sbbc.c,v 1.2 2008/07/07 14:46:18 kettenis Exp $ */ +/* $OpenBSD: sbbc.c,v 1.3 2008/07/10 20:27:36 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis * @@ -52,6 +52,10 @@ extern todr_chip_handle_t todr_handle; #define SBBC_SRAM_OFFSET 0x900000 #define SBBC_SRAM_SIZE 0x20000 /* 128KB SRAM */ +#define SBBC_PCI_INT_STATUS 0x2320 +#define SBBC_PCI_INT_ENABLE 0x2330 +#define SBBC_PCI_ENABLE_INT_A 0x11 + #define SBBC_EPLD_INTERRUPT 0x13 #define SBBC_EPLD_INTERRUPT_ON 0x01 @@ -120,14 +124,17 @@ struct sbbc_softc { bus_space_handle_t sc_sram_ioh; caddr_t sc_sram; uint32_t sc_sram_toc; + void * sc_ih; struct sparc_bus_space_tag sc_bbt; struct tty *sc_tty; struct timeout sc_to; caddr_t sc_sram_cons; - uint32_t *sc_sram_intr_enabled; - uint32_t *sc_sram_intr_reason; + uint32_t *sc_sram_solscie; + uint32_t *sc_sram_solscir; + uint32_t *sc_sram_scsolie; + uint32_t *sc_sram_scsolir; }; struct sbbc_softc *sbbc_cons_input; @@ -144,6 +151,7 @@ struct cfdriver sbbc_cd = { NULL, "sbbc", DV_DULL }; +int sbbc_intr(void *); void sbbc_send_intr(struct sbbc_softc *sc); void sbbc_attach_tod(struct sbbc_softc *, uint32_t); @@ -178,6 +186,7 @@ sbbc_attach(struct device *parent, struct device *self, void *aux) struct sbbc_sram_toc *toc; bus_addr_t base; bus_size_t size; + pci_intr_handle_t ih; int chosen, iosram; int i; @@ -192,25 +201,45 @@ sbbc_attach(struct device *parent, struct device *self, void *aux) return; } + if (bus_space_map(sc->sc_iot, base + SBBC_REGS_OFFSET, + SBBC_REGS_SIZE, 0, &sc->sc_regs_ioh)) { + printf(": can't map register space\n"); + return; + } + if (bus_space_map(sc->sc_iot, base + SBBC_EPLD_OFFSET, SBBC_EPLD_SIZE, 0, &sc->sc_epld_ioh)) { printf(": can't map EPLD registers\n"); - return; + goto unmap_regs; } if (bus_space_map(sc->sc_iot, base + SBBC_SRAM_OFFSET, SBBC_SRAM_SIZE, 0, &sc->sc_sram_ioh)) { printf(": can't map SRAM\n"); - return; + goto unmap_epld; + } + + if (pci_intr_map(pa, &ih)) { + printf(": unable to map interrupt\n"); + goto unmap_sram; } + printf(": %s\n", pci_intr_string(pa->pa_pc, ih)); + + sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, + sbbc_intr, sc, sc->sc_dv.dv_xname); + if (sc->sc_ih == NULL) { + printf("%s: unable to establish interrupt\n"); + goto unmap_sram; + } + + bus_space_write_4(sc->sc_iot, sc->sc_regs_ioh, + SBBC_PCI_INT_ENABLE, SBBC_PCI_ENABLE_INT_A); /* Check if we are the chosen one. */ chosen = OF_finddevice("/chosen"); if (OF_getprop(chosen, "iosram", &iosram, sizeof(iosram)) <= 0 || - PCITAG_NODE(pa->pa_tag) != iosram) { - printf("\n"); + PCITAG_NODE(pa->pa_tag) != iosram) return; - } /* SRAM TOC offset defaults to 0. */ if (OF_getprop(chosen, "iosram-toc", &sc->sc_sram_toc, @@ -222,15 +251,19 @@ sbbc_attach(struct device *parent, struct device *self, void *aux) for (i = 0; i < toc->toc_ntags; i++) { if (strcmp(toc->toc_tag[i].tag_key, "SOLSCIE") == 0) - sc->sc_sram_intr_enabled = (uint32_t *) + sc->sc_sram_solscie = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); if (strcmp(toc->toc_tag[i].tag_key, "SOLSCIR") == 0) - sc->sc_sram_intr_reason = (uint32_t *) + sc->sc_sram_solscir = (uint32_t *) + (sc->sc_sram + toc->toc_tag[i].tag_offset); + if (strcmp(toc->toc_tag[i].tag_key, "SCSOLIE") == 0) + sc->sc_sram_scsolie = (uint32_t *) + (sc->sc_sram + toc->toc_tag[i].tag_offset); + if (strcmp(toc->toc_tag[i].tag_key, "SCSOLIR") == 0) + sc->sc_sram_scsolir = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); } - *sc->sc_sram_intr_enabled |= SBBC_SRAM_CONS_OUT; - for (i = 0; i < toc->toc_ntags; i++) { if (strcmp(toc->toc_tag[i].tag_key, "TODDATA") == 0) sbbc_attach_tod(sc, toc->toc_tag[i].tag_offset); @@ -238,7 +271,42 @@ sbbc_attach(struct device *parent, struct device *self, void *aux) sbbc_attach_cons(sc, toc->toc_tag[i].tag_offset); } - printf("\n"); + return; + + unmap_sram: + bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_SRAM_SIZE); + unmap_epld: + bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_EPLD_SIZE); + unmap_regs: + bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_REGS_SIZE); +} + +int +sbbc_intr(void *arg) +{ + struct sbbc_softc *sc = arg; + uint32_t status, reason; + + status = bus_space_read_4(sc->sc_iot, sc->sc_regs_ioh, + SBBC_PCI_INT_STATUS); + if (status == 0) + return (0); + + /* Sigh, we cannot use compare and swap for non-cachable memory. */ + reason = *sc->sc_sram_scsolir; + *sc->sc_sram_scsolir = 0; + +#ifdef DDB + if (reason & SBBC_SRAM_CONS_BRK && sc == sbbc_cons_input) { + if (db_console) + Debugger(); + } +#endif + + /* Ack interrupt. */ + bus_space_write_4(sc->sc_iot, sc->sc_regs_ioh, + SBBC_PCI_INT_STATUS, status); + return (1); } void @@ -298,6 +366,10 @@ sbbc_attach_cons(struct sbbc_softc *sc, uint32_t offset) int sgcn_is_input, sgcn_is_output, node, maj; char buf[32]; + if (sc->sc_sram_solscie == NULL || sc->sc_sram_solscir == NULL || + sc->sc_sram_scsolie == NULL || sc->sc_sram_scsolir == NULL) + return; + cons = (struct sbbc_sram_cons *)(sc->sc_sram + offset); if (cons->cons_magic != SBBC_CONS_MAGIC || cons->cons_version < SBBC_CONS_VERSION) @@ -309,6 +381,9 @@ sbbc_attach_cons(struct sbbc_softc *sc, uint32_t offset) timeout_set(&sc->sc_to, sbbctimeout, sc); + *sc->sc_sram_solscie |= SBBC_SRAM_CONS_OUT; + *sc->sc_sram_scsolie |= SBBC_SRAM_CONS_BRK; + /* Take over console input. */ prom_serengeti_set_console_input("CON_CLNT"); @@ -340,7 +415,7 @@ sbbc_attach_cons(struct sbbc_softc *sc, uint32_t offset) /* Let current output drain. */ DELAY(2000000); - printf(": console"); + printf("%s: console\n", sc->sc_dv.dv_xname); } } @@ -385,7 +460,7 @@ sbbc_cnputc(dev_t dev, int c) wrptr = cons->cons_out_begin; cons->cons_out_wrptr = wrptr; - *sc->sc_sram_intr_reason |= SBBC_SRAM_CONS_OUT; + *sc->sc_sram_solscir |= SBBC_SRAM_CONS_OUT; sbbc_send_intr(sc); }