summaryrefslogtreecommitdiff
path: root/sys/arch/loongson
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-05-08 21:59:57 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-05-08 21:59:57 +0000
commitc60925a8da6f5ba6b3c5a172c87f11377364205e (patch)
tree95f9bb1dd0b2b987e34b70d89d19f31684265de3 /sys/arch/loongson
parent82e9f80967a1e3668ead006f748d60ca2293f5b9 (diff)
Huge work-in-progress commit to support Loongson 2E-based evaluation boards
with a VIA 686 southbridge. Features: - 686 setup code (no thanks to PMON for not initializing the beast). - work in progress ISA interrupt handling code. - support for vga(4) compatible devices as console, in PC-compatible text mode. - move legacy (ISA) support code out of bonito(4) to make things clearer. - support more than 256MB on 2E-based systems. Tested on a generic 2E-based evaluation board by someone who wishes to remain anonymous; you know who you are, thank you very much for testing.
Diffstat (limited to 'sys/arch/loongson')
-rw-r--r--sys/arch/loongson/conf/GENERIC11
-rw-r--r--sys/arch/loongson/conf/RAMDISK8
-rw-r--r--sys/arch/loongson/conf/files.loongson11
-rw-r--r--sys/arch/loongson/dev/apm.c9
-rw-r--r--sys/arch/loongson/dev/bonito.c522
-rw-r--r--sys/arch/loongson/dev/bonito_irq.h46
-rw-r--r--sys/arch/loongson/dev/bonitoreg.h7
-rw-r--r--sys/arch/loongson/dev/bonitovar.h7
-rw-r--r--sys/arch/loongson/dev/glxpcib.c6
-rw-r--r--sys/arch/loongson/dev/kb3310.c7
-rw-r--r--sys/arch/loongson/dev/pcib.c127
-rw-r--r--sys/arch/loongson/include/autoconf.h5
-rw-r--r--sys/arch/loongson/include/bus.h3
-rw-r--r--sys/arch/loongson/include/isa_machdep.h28
-rw-r--r--sys/arch/loongson/loongson/gdium_machdep.c6
-rw-r--r--sys/arch/loongson/loongson/generic2e_machdep.c586
-rw-r--r--sys/arch/loongson/loongson/isa_machdep.c118
-rw-r--r--sys/arch/loongson/loongson/loongson2_machdep.c24
-rw-r--r--sys/arch/loongson/loongson/machdep.c42
-rw-r--r--sys/arch/loongson/loongson/pciide_machdep.c16
-rw-r--r--sys/arch/loongson/loongson/wscons_machdep.c81
-rw-r--r--sys/arch/loongson/loongson/yeeloong_machdep.c207
22 files changed, 1430 insertions, 447 deletions
diff --git a/sys/arch/loongson/conf/GENERIC b/sys/arch/loongson/conf/GENERIC
index 9054d9bf57f..4c829bcd639 100644
--- a/sys/arch/loongson/conf/GENERIC
+++ b/sys/arch/loongson/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.21 2010/03/03 20:57:28 mk Exp $
+# $OpenBSD: GENERIC,v 1.22 2010/05/08 21:59:53 miod Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -71,6 +71,15 @@ ohci* at voyager?
smfb* at voyager?
wsdisplay* at smfb?
+# Generic 2E systems (in addition to the Fuloong devices)
+pcib* at pci?
+isa0 at pcib?
+vga* at pci?
+wsdisplay* at vga?
+auvia* at pci?
+audio* at auvia?
+viaenv* at pci?
+
# USB Controllers
ohci* at pci?
uhci* at pci?
diff --git a/sys/arch/loongson/conf/RAMDISK b/sys/arch/loongson/conf/RAMDISK
index eea22315c1c..dafdb4dcb40 100644
--- a/sys/arch/loongson/conf/RAMDISK
+++ b/sys/arch/loongson/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.11 2010/03/02 20:54:51 miod Exp $
+# $OpenBSD: RAMDISK,v 1.12 2010/05/08 21:59:53 miod Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -75,6 +75,12 @@ ohci* at voyager?
smfb* at voyager?
wsdisplay* at smfb?
+# Generic 2E systems (in addition to the Fuloong devices)
+pcib* at pci?
+isa0 at pcib?
+vga* at pci?
+wsdisplay* at vga?
+
# USB Controllers
ohci* at pci?
uhci* at pci?
diff --git a/sys/arch/loongson/conf/files.loongson b/sys/arch/loongson/conf/files.loongson
index 0efef75c2bb..1fb209cdc08 100644
--- a/sys/arch/loongson/conf/files.loongson
+++ b/sys/arch/loongson/conf/files.loongson
@@ -1,4 +1,4 @@
-# $OpenBSD: files.loongson,v 1.10 2010/03/03 13:33:27 jasper Exp $
+# $OpenBSD: files.loongson,v 1.11 2010/05/08 21:59:53 miod Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -18,6 +18,8 @@ file arch/loongson/loongson/bus_space.c
file arch/loongson/loongson/conf.c
file arch/loongson/loongson/disksubr.c disk
file arch/loongson/loongson/gdium_machdep.c
+file arch/loongson/loongson/generic2e_machdep.c
+file arch/loongson/loongson/isa_machdep.c isa
file arch/loongson/loongson/loongson2_machdep.c
file arch/loongson/loongson/machdep.c
file arch/loongson/loongson/mutex.c
@@ -36,6 +38,7 @@ include "dev/isa/files.isa"
include "dev/isa/files.isapnp"
include "dev/mii/files.mii"
include "dev/pci/files.pci"
+include "dev/pci/files.agp"
include "dev/pckbc/files.pckbc"
include "dev/usb/files.usb"
include "dev/bluetooth/files.bluetooth"
@@ -66,7 +69,11 @@ file arch/loongson/dev/glx.c bonito & pci
device glxpcib: isabus, gpiobus
attach glxpcib at pci
file arch/loongson/dev/glxpcib.c glxpcib
-file arch/loongson/dev/pcib.c glxpcib
+
+# Other PCI-ISA bridges
+device pcib: isabus
+attach pcib at pci
+file arch/loongson/dev/pcib.c pcib | glxpcib
# Lemote Yeeloong RTC
device mcclock
diff --git a/sys/arch/loongson/dev/apm.c b/sys/arch/loongson/dev/apm.c
index 919c6120e75..e5822bf861e 100644
--- a/sys/arch/loongson/dev/apm.c
+++ b/sys/arch/loongson/dev/apm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apm.c,v 1.2 2010/02/28 09:37:28 otto Exp $ */
+/* $OpenBSD: apm.c,v 1.3 2010/05/08 21:59:56 miod Exp $ */
/*-
* Copyright (c) 2001 Alexander Guy. All rights reserved.
@@ -111,7 +111,12 @@ apmmatch(struct device *parent, void *match, void *aux)
{
struct mainbus_attach_args *maa = aux;
- if (strcmp(maa->maa_name, apm_cd.cd_name) == 0)
+ /*
+ * It only makes sense to attach on a 2F system, since 2E do not
+ * feature speed throttling, and we do not support 2E-based
+ * notebooks yet (assuming there are any).
+ */
+ if (strcmp(maa->maa_name, apm_cd.cd_name) == 0 && loongson_ver == 0x2f)
return (1);
return (0);
}
diff --git a/sys/arch/loongson/dev/bonito.c b/sys/arch/loongson/dev/bonito.c
index 58c716b5eed..df9d2b7e211 100644
--- a/sys/arch/loongson/dev/bonito.c
+++ b/sys/arch/loongson/dev/bonito.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonito.c,v 1.13 2010/03/02 20:53:12 miod Exp $ */
+/* $OpenBSD: bonito.c,v 1.14 2010/05/08 21:59:56 miod Exp $ */
/* $NetBSD: bonito_mainbus.c,v 1.11 2008/04/28 20:23:10 martin Exp $ */
/* $NetBSD: bonito_pci.c,v 1.5 2008/04/28 20:23:28 martin Exp $ */
@@ -50,10 +50,6 @@
* PCI configuration space support for the Loongson PCI and memory controller
* chip, which is derived from the Algorithmics BONITO chip.
*/
-/*
- * XXX The legacy interrupt scheme is entangled and as many parts as
- * XXX possible should move to pcib.c...
- */
#include <sys/param.h>
#include <sys/systm.h>
@@ -61,8 +57,6 @@
#include <sys/extent.h>
#include <sys/malloc.h>
-#include <mips64/archtype.h>
-
#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/intr.h>
@@ -72,13 +66,12 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>
-#include <dev/isa/isareg.h>
-#include <dev/isa/isavar.h>
-
#include <loongson/dev/bonitoreg.h>
#include <loongson/dev/bonitovar.h>
#include <loongson/dev/bonito_irq.h>
+#include <uvm/uvm_extern.h>
+
#if 0
#define BONITO_DEBUG
#endif
@@ -87,8 +80,7 @@ int bonito_match(struct device *, void *, void *);
void bonito_attach(struct device *, struct device *, void *);
const struct cfattach bonito_ca = {
- sizeof(struct bonito_softc),
- bonito_match, bonito_attach
+ sizeof(struct bonito_softc), bonito_match, bonito_attach
};
struct cfdriver bonito_cd = {
@@ -101,7 +93,9 @@ bus_addr_t bonito_pa_to_device(paddr_t);
paddr_t bonito_device_to_pa(bus_addr_t);
void bonito_intr_makemasks(void);
-uint32_t bonito_intr(uint32_t, struct trap_frame *);
+uint32_t bonito_intr_2e(uint32_t, struct trap_frame *);
+uint32_t bonito_intr_2f(uint32_t, struct trap_frame *);
+void bonito_intr_dispatch(uint64_t, int, struct trap_frame *);
void bonito_attach_hook(struct device *, struct device *,
struct pcibus_attach_args *);
@@ -122,15 +116,6 @@ int bonito_conf_addr(const struct bonito_config *, pcitag_t, int,
u_int32_t *, u_int32_t *);
void bonito_splx(int);
-void bonito_setintrmask(int);
-
-uint loongson_get_isa_imr(void);
-uint loongson_get_isa_isr(void);
-void loongson_set_isa_imr(uint);
-void loongson_isa_specific_eoi(int);
-uint32_t loongson_isa_intr(uint32_t, struct trap_frame *);
-void loongson_isa_splx(int);
-void loongson_isa_setintrmask(int);
/*
* Bonito interrupt handling declarations.
@@ -140,8 +125,6 @@ struct intrhand *bonito_intrhand[BONITO_NINTS];
uint64_t bonito_intem;
uint64_t bonito_imask[NIPLS];
-uint loongson_isaimr;
-
struct machine_bus_dma_tag bonito_bus_dma_tag = {
._dmamap_create = _dmamap_create,
._dmamap_destroy = _dmamap_destroy,
@@ -238,8 +221,7 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
* We need to make sure we never try to access an unimplemented
* register...
*/
- if (curcpu()->ci_hw.type == MIPS_LOONGSON2 &&
- (curcpu()->ci_hw.c0prid & 0xff) == 0x2f - 0x2c)
+ if (loongson_ver == 0x2f)
sc->sc_compatible = 0;
else
sc->sc_compatible = 1;
@@ -324,16 +306,16 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
REGVAL(BONITO_INTENCLR) = 0xffffffff;
(void)REGVAL(BONITO_INTENCLR);
- if (bc->bc_legacy_pic) {
- set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr);
- set_intr(INTPRI_ISA, CR_INT_0, loongson_isa_intr);
- loongson_isaimr = loongson_get_isa_imr();
- register_splx_handler(loongson_isa_splx);
- } else {
- set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr);
- register_splx_handler(bonito_splx);
+ if (sc->sc_compatible) {
+ bonito_intem |= BONITO_INTRMASK_MASTERERR;
}
+ if (loongson_ver == 0x2f)
+ set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr_2f);
+ else
+ set_intr(INTPRI_BONITO, CR_INT_0, bonito_intr_2e);
+ register_splx_handler(bonito_splx);
+
/*
* Attach PCI bus.
*/
@@ -439,10 +421,45 @@ bonito_intr_establish(int irq, int type, int level, int (*handler)(void *),
}
void
-bonito_intr_disestablish(void *ih)
+bonito_intr_disestablish(void *vih)
{
- /* XXX */
- panic("%s not implemented", __func__);
+ struct intrhand *ih = (struct intrhand *)vih;
+ struct intrhand **p, *q;
+ int irq = ih->ih_irq;
+ int s;
+
+#ifdef DIAGNOSTIC
+ if (irq >= BONITO_NINTS || irq == BONITO_ISA_IRQ(2) || irq < 0)
+ panic("bonito_intr_disestablish: illegal irq %d", irq);
+#endif
+
+ s = splhigh();
+
+ evcount_detach(&ih->ih_count);
+
+ for (p = &bonito_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
+ if (q == ih)
+ break;
+#ifdef DIAGNOSTIC
+ if (q == NULL)
+ panic("bonito_intr_disestablish: never registered");
+#endif
+ *p = ih->ih_next;
+
+ if (ih->ih_next == NULL && p == &bonito_intrhand[irq]) {
+ bonito_intem &= ~(1UL << irq);
+ bonito_intr_makemasks();
+ /*
+ * No need to clear a bit in INTEN through INTCLR,
+ * splhigh() took care of disabling everything and
+ * splx() will not reenable this source after the
+ * mask update.
+ */
+ }
+
+ splx(s);
+
+ free(ih, M_DEVBUF);
}
/*
@@ -472,17 +489,20 @@ bonito_setintrmask(int level)
uint32_t sr;
active = bonito_intem & ~bonito_imask[level];
- /* don't bother masking high bits, there are no isa interrupt sources */
- clear = bonito_imask[level];
- set = active;
+ /* be sure to mask high bits, there may be other interrupt sources */
+ clear = BONITO_DIRECT_MASK(bonito_imask[level]);
+ set = BONITO_DIRECT_MASK(active);
sr = disableintr();
- if (clear != 0)
+ if (clear != 0) {
REGVAL(BONITO_INTENCLR) = clear;
- if (set != 0)
+ (void)REGVAL(BONITO_INTENCLR);
+ }
+ if (set != 0) {
REGVAL(BONITO_INTENSET) = set;
- (void)REGVAL(BONITO_INTENSET);
+ (void)REGVAL(BONITO_INTENSET);
+ }
setsr(sr);
}
@@ -543,12 +563,66 @@ bonito_intr_makemasks()
*/
uint32_t
-bonito_intr(uint32_t hwpend, struct trap_frame *frame)
+bonito_intr_2e(uint32_t hwpend, struct trap_frame *frame)
+{
+ uint64_t imr, isr, mask;
+
+ isr = REGVAL(BONITO_INTISR);
+
+ /*
+ * According to Linux code, Bonito64 - at least on Loongson
+ * systems - triggers an interrupt during DMA, which is to be
+ * ignored. Smells like a chip errata to me.
+ */
+ while (ISSET(isr, BONITO_INTRMASK_MASTERERR)) {
+ delay(1);
+ isr = REGVAL(BONITO_INTISR);
+ }
+
+ isr &= BONITO_INTRMASK_GPIN;
+ imr = REGVAL(BONITO_INTEN);
+ isr &= imr;
+#ifdef DEBUG
+ printf("pci interrupt: imr %04x isr %04x\n", imr, isr);
+#endif
+ if (isr == 0)
+ return 0; /* not for us */
+
+ /*
+ * Mask all pending interrupts.
+ */
+ REGVAL(BONITO_INTENCLR) = isr;
+ (void)REGVAL(BONITO_INTENCLR);
+
+ /*
+ * If interrupts are spl-masked, mask them and wait for splx()
+ * to reenable them when necessary.
+ */
+ if ((mask = isr & bonito_imask[frame->ipl]) != 0) {
+ isr &= ~mask;
+ imr &= ~mask;
+ }
+
+ /*
+ * Now process allowed interrupts.
+ */
+ if (isr != 0) {
+ bonito_intr_dispatch(isr, 30, frame);
+
+ /*
+ * Reenable interrupts which have been serviced.
+ */
+ REGVAL(BONITO_INTENSET) = imr;
+ (void)REGVAL(BONITO_INTENSET);
+ }
+
+ return hwpend;
+}
+
+uint32_t
+bonito_intr_2f(uint32_t hwpend, struct trap_frame *frame)
{
uint64_t imr, isr, mask;
- int bit;
- struct intrhand *ih;
- int rc;
isr = REGVAL(BONITO_INTISR) & LOONGSON_INTRMASK_LVL4;
imr = REGVAL(BONITO_INTEN);
@@ -578,39 +652,9 @@ bonito_intr(uint32_t hwpend, struct trap_frame *frame)
* Now process allowed interrupts.
*/
if (isr != 0) {
- int lvl, bitno;
- uint64_t tmpisr;
-
- /* Service higher level interrupts first */
- bit = LOONGSON_INTR_DRAM_PARERR; /* skip non-pci interrupts */
- for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
- tmpisr = isr & (bonito_imask[lvl] ^ bonito_imask[lvl - 1]);
- if (tmpisr == 0)
- continue;
- for (bitno = bit, mask = 1UL << bitno; mask != 0;
- bitno--, mask >>= 1) {
- if ((tmpisr & mask) == 0)
- continue;
-
- rc = 0;
- for (ih = bonito_intrhand[bitno]; ih != NULL;
- ih = ih->ih_next) {
- if ((*ih->ih_fun)(ih->ih_arg) != 0) {
- rc = 1;
- ih->ih_count.ec_count++;
- }
- }
- if (rc == 0)
- printf("spurious interrupt %d\n",
- bitno);
-
- if ((isr ^= mask) == 0)
- goto done;
- if ((tmpisr ^= mask) == 0)
- break;
- }
- }
-done:
+ bonito_intr_dispatch(isr,
+ LOONGSON_INTR_DRAM_PARERR /* skip non-pci interrupts */,
+ frame);
/*
* Reenable interrupts which have been serviced.
@@ -622,6 +666,56 @@ done:
return hwpend;
}
+void
+bonito_intr_dispatch(uint64_t isr, int startbit, struct trap_frame *frame)
+{
+ int lvl, bitno;
+ uint64_t tmpisr, mask;
+ struct intrhand *ih;
+ int rc;
+
+ /* Service higher level interrupts first */
+ for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
+ tmpisr = isr & (bonito_imask[lvl] ^ bonito_imask[lvl - 1]);
+ if (tmpisr == 0)
+ continue;
+ for (bitno = startbit, mask = 1UL << bitno; mask != 0;
+ bitno--, mask >>= 1) {
+ if ((tmpisr & mask) == 0)
+ continue;
+
+ rc = 0;
+ for (ih = bonito_intrhand[bitno]; ih != NULL;
+ ih = ih->ih_next) {
+ splraise(ih->ih_level);
+ if ((*ih->ih_fun)(ih->ih_arg) != 0) {
+ rc = 1;
+ ih->ih_count.ec_count++;
+ }
+ __asm__ (".set noreorder\n");
+ curcpu()->ci_ipl = frame->ipl;
+ __asm__ ("sync\n\t.set reorder\n");
+ }
+ if (rc == 0) {
+ printf("spurious interrupt %d\n", bitno);
+#ifdef DEBUG
+ printf("ISR %08x IMR %08x ipl %d mask %08x\n",
+ REGVAL(BONITO_INTISR), REGVAL(BONITO_INTEN),
+ frame->ipl, bonito_imask[frame->ipl]);
+#ifdef DDB
+ Debugger();
+#endif
+#endif
+ }
+
+ if ((isr ^= mask) == 0)
+ return;
+ if ((tmpisr ^= mask) == 0)
+ break;
+ }
+ }
+}
+
/*
* various PCI helpers
*/
@@ -832,7 +926,7 @@ bonito_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
const struct bonito_config *bc = sc->sc_bonito;
int bus, dev, fn, pin;
- *ihp = -1;
+ *ihp = (pci_intr_handle_t)-1;
if (pa->pa_intrpin == 0) /* no interrupt needed */
return 1;
@@ -852,7 +946,7 @@ bonito_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
if (bus == 0)
*ihp = (*bc->bc_intr_map)(dev, fn, pa->pa_intrpin);
- if (*ihp < 0)
+ if (*ihp == (pci_intr_handle_t)-1)
return 1;
}
@@ -866,7 +960,7 @@ bonito_pci_intr_string(void *cookie, pci_intr_handle_t ih)
if (BONITO_IRQ_IS_ISA(ih))
snprintf(irqstr, sizeof irqstr, "isa irq %d",
- ih - BONITO_NDIRECT);
+ BONITO_IRQ_TO_ISA(ih));
else
snprintf(irqstr, sizeof irqstr, "irq %d", ih);
return irqstr;
@@ -886,230 +980,9 @@ bonito_pci_intr_disestablish(void *cookie, void *ihp)
}
/*
- * Legacy (ISA) interrupt handling
- */
-
-/*
- * Process legacy interrupts.
- *
- * XXX ISA interrupts only occur on LOONGSON_INTR_INT0, but since the other
- * XXX LOONGSON_INTR_INT# are unmaskable, bad things will happen if they
- * XXX are triggered...
- */
-
-/*
- * Interrupt dispatcher.
- */
-uint32_t
-loongson_isa_intr(uint32_t hwpend, struct trap_frame *frame)
-{
- uint64_t imr, isr, mask;
- int bit;
- struct intrhand *ih;
- int rc;
-
- isr = loongson_get_isa_isr();
- imr = loongson_get_isa_imr();
-
- isr &= imr;
- isr &= ~(1 << 2); /* cascade */
-#ifdef DEBUG
- printf("isa interrupt: imr %04x isr %04x\n", imr, isr);
-#endif
- if (isr == 0)
- return 0; /* not for us */
-
- /*
- * Mask all pending interrupts.
- */
-
- loongson_set_isa_imr(imr & ~isr);
-
- /*
- * If interrupts are spl-masked, mask them and wait for splx()
- * to reenable them when necessary.
- */
- if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) {
- isr &= ~mask;
- imr &= ~mask;
- }
-
- /*
- * Now process allowed interrupts.
- */
- if (isr != 0) {
- int lvl, bitno;
- uint64_t tmpisr;
-
- /* Service higher level interrupts first */
- bit = BONITO_NISA - 1;
- for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
- tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^
- bonito_imask[lvl - 1]);
- if (tmpisr == 0)
- continue;
- for (bitno = bit, mask = 1UL << bitno; mask != 0;
- bitno--, mask >>= 1) {
- if ((tmpisr & mask) == 0)
- continue;
-
- rc = 0;
- for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)];
- ih != NULL; ih = ih->ih_next) {
- if ((*ih->ih_fun)(ih->ih_arg) != 0) {
- rc = 1;
- ih->ih_count.ec_count++;
- }
- }
- if (rc == 0)
- printf("spurious isa interrupt %d\n",
- bitno);
-
- loongson_isa_specific_eoi(bitno);
-
- if ((isr ^= mask) == 0)
- goto done;
- if ((tmpisr ^= mask) == 0)
- break;
- }
- }
-done:
-
- /*
- * Reenable interrupts which have been serviced.
- */
- loongson_set_isa_imr(imr);
- }
-
- return hwpend;
-}
-
-#define REGVAL8(x) *((volatile u_int8_t *)PHYS_TO_XKPHYS(x, CCA_NC))
-
-uint
-loongson_get_isa_imr()
-{
- uint imr1, imr2;
-
- imr1 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1);
- imr1 &= ~(1 << 2); /* hide cascade */
- imr2 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1);
-
- return (imr2 << 8) | imr1;
-}
-
-uint
-loongson_get_isa_isr()
-{
- uint isr1, isr2;
-
- isr1 = 0xff & REGVAL8(BONITO_PCIIO_BASE + IO_ICU1);
- isr2 = 0xff & REGVAL8(BONITO_PCIIO_BASE + IO_ICU2);
-
- return (isr2 << 8) | isr1;
-}
-
-void
-loongson_set_isa_imr(uint newimr)
-{
- uint imr1, imr2;
-
- imr1 = 0xff & ~newimr;
- imr1 &= ~(1 << 2); /* enable cascade */
- imr2 = 0xff & ~(newimr >> 8);
-
- /*
- * For some reason, trying to write the same value to the PIC
- * registers causes an immediate system freeze, so we only do
- * this if the value changes.
- * Note that interrupts have been disabled by the caller.
- */
- if ((newimr ^ loongson_isaimr) & 0xff00) {
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1) = imr2;
- (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1);
- }
- if ((newimr ^ loongson_isaimr) & 0x00ff) {
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1) = imr1;
- (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1);
- }
- loongson_isaimr = newimr;
-}
-
-void
-loongson_isa_specific_eoi(int bit)
-{
- if (bit & 8) {
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 0) = 0x60 | (bit & 7);
- (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 0);
- bit = 2;
- }
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 0) = 0x60 | bit;
- (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 0);
-}
-
-/*
- * Update interrupt masks. This is for designs with legacy PIC.
+ * bus_space mapping routines.
*/
-void
-loongson_isa_splx(int newipl)
-{
- struct cpu_info *ci = curcpu();
-
- /* Update masks to new ipl. Order highly important! */
- __asm__ (".set noreorder\n");
- ci->ci_ipl = newipl;
- __asm__ ("sync\n\t.set reorder\n");
- loongson_isa_setintrmask(newipl);
- /* If we still have softints pending trigger processing. */
- if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT)
- setsoftintr0();
-}
-
-void
-loongson_isa_setintrmask(int level)
-{
- uint64_t active;
- uint32_t clear, set;
- uint32_t sr;
-
- active = bonito_intem & ~bonito_imask[level];
- clear = BONITO_DIRECT_MASK(bonito_imask[level]);
- set = BONITO_DIRECT_MASK(active);
-
- sr = disableintr();
-
- if (clear != 0)
- REGVAL(BONITO_INTENCLR) = clear;
- if (set != 0)
- REGVAL(BONITO_INTENSET) = set;
- (void)REGVAL(BONITO_INTENSET);
-
- loongson_set_isa_imr(BONITO_ISA_MASK(active));
-
- setsr(sr);
-}
-
-void
-isa_attach_hook(struct device *parent, struct device *self,
- struct isabus_attach_args *iba)
-{
-}
-
-void *
-isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
- int (*handler)(void *), void *arg, char *name)
-{
- return bonito_intr_establish(BONITO_ISA_IRQ(irq), type, level,
- handler, arg, name);
-}
-
-void
-isa_intr_disestablish(void *v, void *ih)
-{
- bonito_intr_disestablish(ih);
-}
-
/*
* Legacy I/O access protection.
* Since MI ISA code does not expect bus access to cause any failure when
@@ -1129,7 +1002,7 @@ bonito_io_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
if (offs >= r->start && offs + size <= r->end)
break;
- if (r->start == 0)
+ if (r->end == 0)
return ENXIO;
}
@@ -1154,36 +1027,35 @@ bonito_mem_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
bus_addr_t pcilo_w[3];
bus_addr_t ws, we, w;
bus_addr_t end = offs + size - 1;
- int is2f, pcilo_window;
+ int pcilo_window;
/*
* Try a PCIHI mapping first.
*/
- /* may be used before curcpu() points to valid data */
- if ((cp0_get_prid() & 0xffff) ==
- ((MIPS_LOONGSON2 << 8) | (0x2f - 0x2c)))
- is2f = 1;
- else
- is2f = 0;
-
- if (is2f) {
+ if (loongson_ver == 0x2f) {
if (offs >= LS2F_PCIHI_BASE && end <= LS2F_PCIHI_TOP) {
*bshp = t->bus_base + offs;
return 0;
}
} else {
- /* PCI1.5 */
- if (offs >= BONITO_PCIHI_BASE && end <= BONITO_PCIHI_TOP) {
- *bshp = t->bus_base + offs;
- return 0;
- }
+ /*
+ * Only try HI space if we do not have memory setup there.
+ */
+ if (physmem <= atop(BONITO_PCILO_BASE)) {
+ /* PCI1.5 */
+ if (offs >= BONITO_PCIHI_BASE &&
+ end <= BONITO_PCIHI_TOP) {
+ *bshp = t->bus_base + offs;
+ return 0;
+ }
- /* PCI2 */
- w = pcimap & BONITO_PCIMAP_PCIMAP_2 ? 0x80000000UL : 0;
- if (offs >= w && end < (w + 0x80000000UL)) {
- *bshp = t->bus_base + 0x80000000UL + (offs - w);
- return 0;
+ /* PCI2 */
+ w = pcimap & BONITO_PCIMAP_PCIMAP_2 ? 0x80000000UL : 0;
+ if (offs >= w && end < (w + 0x80000000UL)) {
+ *bshp = t->bus_base + 0x80000000UL + (offs - w);
+ return 0;
+ }
}
}
diff --git a/sys/arch/loongson/dev/bonito_irq.h b/sys/arch/loongson/dev/bonito_irq.h
index 667a2b991ac..43dcd347d59 100644
--- a/sys/arch/loongson/dev/bonito_irq.h
+++ b/sys/arch/loongson/dev/bonito_irq.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonito_irq.h,v 1.1 2010/02/05 20:51:22 miod Exp $ */
+/* $OpenBSD: bonito_irq.h,v 1.2 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -20,6 +20,10 @@
* Bonito interrupt assignments
*/
+/*
+ * Loongson 2F assignments
+ */
+
#define LOONGSON_INTR_GPIO0 0
#define LOONGSON_INTR_GPIO1 1
#define LOONGSON_INTR_GPIO2 2
@@ -68,25 +72,51 @@
#define LOONGSON_INTRMASK_LVL4 0x000007ff
/*
+ * Loongson 2E (Bonito64) assignments
+ */
+
+#define BONITO_INTRMASK_MBOX 0x0000000f
+#define BONITO_INTR_MBOX 0
+#define BONITO_INTRMASK_DMARDY 0x00000010
+#define BONITO_INTRMASK_DMAEMPTY 0x00000020
+#define BONITO_INTRMASK_COPYRDY 0x00000040
+#define BONITO_INTRMASK_COPYEMPTY 0x00000080
+#define BONITO_INTRMASK_COPYERR 0x00000100
+#define BONITO_INTRMASK_PCIIRQ 0x00000200
+#define BONITO_INTRMASK_MASTERERR 0x00000400
+#define BONITO_INTRMASK_SYSTEMERR 0x00000800
+#define BONITO_INTRMASK_DRAMPERR 0x00001000
+#define BONITO_INTRMASK_RETRYERR 0x00002000
+#define BONITO_INTRMASK_GPIO 0x01ff0000
+#define BONITO_INTR_GPIO 16
+#define BONITO_INTRMASK_GPIN 0x7e000000
+#define BONITO_INTR_GPIN 25
+
+/*
* Bonito interrupt handling recipes:
- * - we have 14 interrupts on Bonito
- * - on the Yeeloong, there are also 16 (well, 15) ISA interrupts with the
+ * - we have up to 32 interrupts at the Bonito level.
+ * - systems with ISA devices also have 16 (well, 15) ISA interrupts with the
* usual 8259 pair. Bonito and ISA interrupts happen on two different levels.
*
- * For simplicity we allocate 16 vectors for direct interrupts, and 16
- * vectors for ISA interrupts as well (which will only be used if we are
- * running on a Yeeloong).
+ * These arbitrary values may be changed as long as interrupt mask variables
+ * use large enough integer types and always use the following macros to
+ * handle interrupt masks.
*/
#define INTPRI_BONITO (INTPRI_CLOCK + 1)
#define INTPRI_ISA (INTPRI_BONITO + 1)
-#define BONITO_NDIRECT 16
+#define BONITO_NDIRECT 32
#define BONITO_NISA 16
#define BONITO_NINTS (BONITO_NDIRECT + BONITO_NISA)
#define BONITO_ISA_IRQ(i) ((i) + BONITO_NDIRECT)
#define BONITO_DIRECT_IRQ(i) (i)
#define BONITO_IRQ_IS_ISA(i) ((i) >= BONITO_NDIRECT)
+#define BONITO_IRQ_TO_ISA(i) ((i) - BONITO_NDIRECT)
-#define BONITO_DIRECT_MASK(imask) ((imask) & ((1 << BONITO_NDIRECT) - 1))
+#define BONITO_DIRECT_MASK(imask) ((imask) & ((1L << BONITO_NDIRECT) - 1))
#define BONITO_ISA_MASK(imask) ((imask) >> BONITO_NDIRECT)
+
+extern struct intrhand *bonito_intrhand[BONITO_NINTS];
+extern uint64_t bonito_intem;
+extern uint64_t bonito_imask[NIPLS];
diff --git a/sys/arch/loongson/dev/bonitoreg.h b/sys/arch/loongson/dev/bonitoreg.h
index d542523f9d5..26c0a4ba09a 100644
--- a/sys/arch/loongson/dev/bonitoreg.h
+++ b/sys/arch/loongson/dev/bonitoreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonitoreg.h,v 1.6 2010/02/28 21:35:41 miod Exp $ */
+/* $OpenBSD: bonitoreg.h,v 1.7 2010/05/08 21:59:56 miod Exp $ */
/* $NetBSD: bonitoreg.h,v 1.6 2005/12/24 20:07:19 perry Exp $ */
/*
@@ -33,6 +33,7 @@
#define BONITO(x) (BONITO_REG_BASE + (x))
#define REGVAL(x) *((volatile u_int32_t *)PHYS_TO_XKPHYS(x, CCA_NC))
+#define REGVAL8(x) *((volatile u_int8_t *)PHYS_TO_XKPHYS(x, CCA_NC))
#define BONITO_FLASH_BASE 0x1c000000UL
#define BONITO_FLASH_SIZE 0x02000000UL
@@ -139,7 +140,9 @@
/* gencfg */
-#define BONITO_GENCFG_OV_EN 0x00000001 /* video accel enable */
+#define LOONGSON_GENCFG_OV_EN 0x00000001 /* video accel enable */
+
+#define BONITO_GENCFG_CPUSELFRESET 0x00000004 /* reset system */
/* pcimap */
diff --git a/sys/arch/loongson/dev/bonitovar.h b/sys/arch/loongson/dev/bonitovar.h
index 1d181be1c77..82147f180ac 100644
--- a/sys/arch/loongson/dev/bonitovar.h
+++ b/sys/arch/loongson/dev/bonitovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonitovar.h,v 1.4 2010/02/12 08:14:02 miod Exp $ */
+/* $OpenBSD: bonitovar.h,v 1.5 2010/05/08 21:59:56 miod Exp $ */
/* $NetBSD: bonitovar.h,v 1.4 2008/04/28 20:23:28 martin Exp $ */
/*-
@@ -33,8 +33,6 @@
#ifndef _LOONGSON_DEV_BONITOVAR_H_
#define _LOONGSON_DEV_BONITOVAR_H_
-#include <dev/pci/pcivar.h>
-
struct bonito_cfg_hook;
struct extent;
@@ -47,8 +45,6 @@ struct bonito_config {
uint32_t bc_intSteer;
uint32_t bc_intPol;
- int bc_legacy_pic; /* nonzero if legacy PIC */
-
/* PCI Attach hook for the first bus */
void (*bc_attach_hook)(pci_chipset_tag_t);
@@ -76,6 +72,7 @@ int bonito_pci_hook(pci_chipset_tag_t, void *,
int bonito_print(void *, const char *);
struct extent
*bonito_get_resource_extent(pci_chipset_tag_t, int);
+void bonito_setintrmask(int);
#endif /* _KERNEL */
#endif /* _LOONGSON_DEV_BONITOVAR_H_ */
diff --git a/sys/arch/loongson/dev/glxpcib.c b/sys/arch/loongson/dev/glxpcib.c
index a11de01827d..9b7d3bdeaf3 100644
--- a/sys/arch/loongson/dev/glxpcib.c
+++ b/sys/arch/loongson/dev/glxpcib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: glxpcib.c,v 1.5 2010/04/21 03:03:26 deraadt Exp $ */
+/* $OpenBSD: glxpcib.c,v 1.6 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
@@ -171,8 +171,10 @@ int
glxpcib_match(struct device *parent, void *match, void *aux)
{
if (pci_matchbyid((struct pci_attach_args *)aux, glxpcib_devices,
- sizeof(glxpcib_devices) / sizeof(glxpcib_devices[0])))
+ nitems(glxpcib_devices))) {
+ /* needs to win over pcib */
return 2;
+ }
return 0;
}
diff --git a/sys/arch/loongson/dev/kb3310.c b/sys/arch/loongson/dev/kb3310.c
index 2749bb4648f..ef3d4c10e1c 100644
--- a/sys/arch/loongson/dev/kb3310.c
+++ b/sys/arch/loongson/dev/kb3310.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kb3310.c,v 1.9 2010/03/02 17:49:38 otto Exp $ */
+/* $OpenBSD: kb3310.c,v 1.10 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2010 Otto Moerbeek <otto@drijf.net>
*
@@ -22,7 +22,9 @@
#include <sys/sensors.h>
#include <sys/timeout.h>
+#include <mips64/archtype.h>
#include <machine/apmvar.h>
+#include <machine/autoconf.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -114,6 +116,9 @@ ykbec_match(struct device *parent, void *match, void *aux)
struct isa_attach_args *ia = aux;
bus_space_handle_t ioh;
+ if (sys_platform->system_type != LOONGSON_YEELOONG)
+ return (0);
+
if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_YKBEC) ||
/* (ia->ia_iosize != 0 && ia->ia_iosize != IO_YKBECSIZE) || XXX isa.c */
ia->ia_maddr != MADDRUNK || ia->ia_msize != 0 ||
diff --git a/sys/arch/loongson/dev/pcib.c b/sys/arch/loongson/dev/pcib.c
index 82707b43219..f6a2b72e8f2 100644
--- a/sys/arch/loongson/dev/pcib.c
+++ b/sys/arch/loongson/dev/pcib.c
@@ -1,29 +1,44 @@
-/* $OpenBSD: pcib.c,v 1.1 2009/12/25 21:04:34 miod Exp $ */
+/* $OpenBSD: pcib.c,v 1.2 2010/05/08 21:59:56 miod Exp $ */
-/*
- * Copyright (c) 2009 Miodrag Vallat.
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
*
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <machine/autoconf.h>
#include <machine/bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
#include <dev/isa/isavar.h>
@@ -32,30 +47,104 @@
#include "isa.h"
+int pcibmatch(struct device *, void *, void *);
void pcibattach(struct device *, struct device *, void *);
+void pcib_callback(struct device *);
int pcib_print(void *, const char *);
+struct pcib_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+};
+
+const struct cfattach pcib_ca = {
+ sizeof(struct pcib_softc), pcibmatch, pcibattach
+};
+
+struct cfdriver pcib_cd = {
+ NULL, "pcib", DV_DULL
+};
+
+int
+pcibmatch(struct device *parent, void *match, void *aux)
+{
+ struct pci_attach_args *pa = aux;
+
+ switch (PCI_VENDOR(pa->pa_id)) {
+ case PCI_VENDOR_INTEL:
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_INTEL_SIO:
+ case PCI_PRODUCT_INTEL_82371MX:
+ case PCI_PRODUCT_INTEL_82371AB_ISA:
+ case PCI_PRODUCT_INTEL_82440MX_ISA:
+ /* The above bridges mis-identify themselves */
+ return (1);
+ }
+ break;
+ case PCI_VENDOR_SIS:
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_SIS_85C503:
+ /* mis-identifies itself as a miscellaneous prehistoric */
+ return (1);
+ }
+ break;
+ case PCI_VENDOR_VIATECH:
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
+ /* mis-identifies itself as a ISA bridge */
+ return (0);
+ }
+ break;
+ }
+
+ if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
+ return (1);
+
+ return (0);
+}
+
void
pcibattach(struct device *parent, struct device *self, void *aux)
{
- struct pci_attach_args *pa = aux;
- struct isabus_attach_args iba;
+ struct pcib_softc *sc = (struct pcib_softc *)self;
+ struct pci_attach_args *pa = (struct pci_attach_args *)aux;
printf("\n");
/*
+ * Wait until all PCI devices are attached before attaching isa;
+ * otherwise this might mess the interrupt setup on some systems.
+ */
+ sc->sc_iot = pa->pa_iot;
+ sc->sc_memt = pa->pa_memt;
+ sc->sc_dmat = pa->pa_dmat;
+ config_defer(self, pcib_callback);
+}
+
+void
+pcib_callback(struct device *self)
+{
+ struct pcib_softc *sc = (struct pcib_softc *)self;
+ struct isabus_attach_args iba;
+
+ /*
* Attach the ISA bus behind this bridge.
* Note that, since we only have a few legacy I/O devices and
* no ISA slots, we can attach immediately.
*/
memset(&iba, 0, sizeof(iba));
iba.iba_busname = "isa";
- iba.iba_iot = pa->pa_iot;
- iba.iba_memt = pa->pa_memt;
+ iba.iba_iot = sc->sc_iot;
+ iba.iba_memt = sc->sc_memt;
#if NISADMA > 0
- iba.iba_dmat = pa->pa_dmat;
+ iba.iba_dmat = sc->sc_dmat;
#endif
- config_found(self, &iba, pcib_print);
+ iba.iba_ic = sys_platform->isa_chipset;
+ if (iba.iba_ic != NULL)
+ config_found(self, &iba, pcib_print);
}
int
diff --git a/sys/arch/loongson/include/autoconf.h b/sys/arch/loongson/include/autoconf.h
index f4b61339d84..0a347e49020 100644
--- a/sys/arch/loongson/include/autoconf.h
+++ b/sys/arch/loongson/include/autoconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.h,v 1.6 2010/02/16 21:31:35 miod Exp $ */
+/* $OpenBSD: autoconf.h,v 1.7 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -36,6 +36,7 @@
#include <machine/bus.h>
struct bonito_config;
+struct mips_isa_chipset;
/*
* List of legacy I/O ranges.
@@ -54,6 +55,7 @@ struct platform {
char *product;
const struct bonito_config *bonito_config;
+ struct mips_isa_chipset *isa_chipset;
const struct legacy_io_range *legacy_io_ranges;
void (*setup)(void);
@@ -65,6 +67,7 @@ struct platform {
};
extern const struct platform *sys_platform;
+extern uint loongson_ver;
struct mainbus_attach_args {
const char *maa_name;
diff --git a/sys/arch/loongson/include/bus.h b/sys/arch/loongson/include/bus.h
index 49b347af863..d9f15ef1ac3 100644
--- a/sys/arch/loongson/include/bus.h
+++ b/sys/arch/loongson/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.2 2010/04/04 11:24:27 miod Exp $ */
+/* $OpenBSD: bus.h,v 1.3 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved.
@@ -43,7 +43,6 @@ typedef u_long bus_addr_t;
typedef u_long bus_size_t;
typedef u_long bus_space_handle_t;
typedef struct mips_bus_space *bus_space_tag_t;
-typedef struct mips_bus_space bus_space_t;
struct mips_bus_space {
bus_addr_t bus_base;
diff --git a/sys/arch/loongson/include/isa_machdep.h b/sys/arch/loongson/include/isa_machdep.h
index 0f2e25023ef..9bfaa58d01e 100644
--- a/sys/arch/loongson/include/isa_machdep.h
+++ b/sys/arch/loongson/include/isa_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa_machdep.h,v 1.1 2009/11/25 19:44:27 miod Exp $ */
+/* $OpenBSD: isa_machdep.h,v 1.2 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2007 Miodrag Vallat.
@@ -24,12 +24,28 @@
#define __NO_ISA_INTR_CHECK
-typedef void *isa_chipset_tag_t;
+typedef struct mips_isa_chipset *isa_chipset_tag_t;
-void isa_attach_hook(struct device *, struct device *,
+struct mips_isa_chipset {
+ void *ic_v;
+
+ void (*ic_attach_hook)(struct device *, struct device *,
+ struct isabus_attach_args *);
+ void *(*ic_intr_establish)(void *, int, int, int, int (*)(void *),
+ void *, char *);
+ void (*ic_intr_disestablish)(void *, void *);
+};
+
+#define isa_attach_hook(p, s, iba) \
+ (*(iba)->iba_ic->ic_attach_hook)((p), (s), (iba))
+#define isa_intr_establish(c, i, t, l, f, a, n) \
+ (*(c)->ic_intr_establish)((c)->ic_v, (i), (t), (l), (f), (a), (n))
+#define isa_intr_disestablish(c, h) \
+ (*(c)->ic_intr_disestablish)((c)->ic_v, (h))
+
+void loongson_generic_isa_attach_hook(struct device *, struct device *,
struct isabus_attach_args *);
-void *isa_intr_establish(void *, int, int, int, int (*)(void *), void *,
- char *);
-void isa_intr_disestablish(void *, void *);
+void loongson_isa_specific_eoi(int);
+void loongson_set_isa_imr(uint);
#endif
diff --git a/sys/arch/loongson/loongson/gdium_machdep.c b/sys/arch/loongson/loongson/gdium_machdep.c
index acde4ca1ea7..05274690f3c 100644
--- a/sys/arch/loongson/loongson/gdium_machdep.c
+++ b/sys/arch/loongson/loongson/gdium_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdium_machdep.c,v 1.5 2010/02/16 21:31:36 miod Exp $ */
+/* $OpenBSD: gdium_machdep.c,v 1.6 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2010 Miodrag Vallat.
@@ -28,6 +28,7 @@
#include <machine/autoconf.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <loongson/dev/bonitoreg.h>
@@ -52,8 +53,6 @@ const struct bonito_config gdium_bonito = {
.bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
- .bc_legacy_pic = 0,
-
.bc_attach_hook = gdium_attach_hook,
.bc_intr_map = gdium_intr_map
};
@@ -64,6 +63,7 @@ const struct platform gdium_platform = {
.product = "Gdium",
.bonito_config = &gdium_bonito,
+ .isa_chipset = NULL,
.legacy_io_ranges = NULL,
.setup = NULL,
diff --git a/sys/arch/loongson/loongson/generic2e_machdep.c b/sys/arch/loongson/loongson/generic2e_machdep.c
new file mode 100644
index 00000000000..e08ccb1b260
--- /dev/null
+++ b/sys/arch/loongson/loongson/generic2e_machdep.c
@@ -0,0 +1,586 @@
+/* $OpenBSD: generic2e_machdep.c,v 1.1 2010/05/08 21:59:56 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*-
+ * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic Loongson 2E code and configuration data.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <mips64/archtype.h>
+#include <machine/autoconf.h>
+#include <machine/pmon.h>
+
+#include <dev/ic/i8259reg.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <loongson/dev/bonitoreg.h>
+#include <loongson/dev/bonitovar.h>
+#include <loongson/dev/bonito_irq.h>
+
+#include "com.h"
+
+#if NCOM > 0
+#include <sys/termios.h>
+#include <dev/ic/comvar.h>
+extern struct mips_bus_space bonito_pci_io_space_tag;
+#endif
+
+void generic2e_device_register(struct device *, void *);
+void generic2e_reset(void);
+
+void generic2e_setup(void);
+
+void generic2e_pci_attach_hook(pci_chipset_tag_t);
+int generic2e_intr_map(int, int, int);
+
+void generic2e_isa_attach_hook(struct device *, struct device *,
+ struct isabus_attach_args *);
+void *generic2e_isa_intr_establish(void *, int, int, int, int (*)(void *),
+ void *, char *);
+void generic2e_isa_intr_disestablish(void *, void *);
+
+uint32_t generic2e_isa_intr(uint32_t, struct trap_frame *);
+
+void via686sb_setup(pci_chipset_tag_t, int);
+
+/* PnP IRQ assignment for VIA686 SuperIO components */
+#define VIA686_IRQ_PCIA 9
+#define VIA686_IRQ_PCIB 10
+#define VIA686_IRQ_PCIC 11
+#define VIA686_IRQ_PCID 13
+
+static int generic2e_via686sb_dev = -1;
+
+const struct bonito_config generic2e_bonito = {
+ .bc_adbase = 11,
+
+ .bc_gpioIE = 0xffffffff,
+ .bc_intEdge = BONITO_INTRMASK_SYSTEMERR | BONITO_INTRMASK_MASTERERR |
+ BONITO_INTRMASK_RETRYERR | BONITO_INTRMASK_MBOX,
+ .bc_intSteer = 0,
+ .bc_intPol = 0,
+
+ .bc_attach_hook = generic2e_pci_attach_hook,
+ .bc_intr_map = generic2e_intr_map
+};
+
+const struct legacy_io_range generic2e_legacy_ranges[] = {
+ /* no isa space access restrictions */
+ { 0, BONITO_PCIIO_LEGACY },
+
+ { 0 }
+};
+
+struct mips_isa_chipset generic2e_isa_chipset = {
+ .ic_v = NULL,
+
+ .ic_attach_hook = generic2e_isa_attach_hook,
+ .ic_intr_establish = generic2e_isa_intr_establish,
+ .ic_intr_disestablish = generic2e_isa_intr_disestablish
+};
+
+const struct platform generic2e_platform = {
+ .system_type = LOONGSON_2E,
+ .vendor = "Generic",
+ .product = "Loongson2E",
+
+ .bonito_config = &generic2e_bonito,
+ .isa_chipset = &generic2e_isa_chipset,
+ .legacy_io_ranges = generic2e_legacy_ranges,
+
+ .setup = generic2e_setup,
+ .device_register = generic2e_device_register,
+
+ .powerdown = NULL,
+ .reset = generic2e_reset
+};
+
+/*
+ * PCI model specific routines
+ */
+
+void
+generic2e_pci_attach_hook(pci_chipset_tag_t pc)
+{
+ pcireg_t id;
+ pcitag_t tag;
+ int dev;
+
+ /*
+ * Check for a VIA 686 southbridge; if one is found, remember
+ * its location, needed by generic2e_intr_map().
+ */
+
+ for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
+ tag = pci_make_tag(pc, 0, dev, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ if (id == PCI_ID_CODE(PCI_VENDOR_VIATECH,
+ PCI_PRODUCT_VIATECH_VT82C686A_ISA)) {
+ generic2e_via686sb_dev = dev;
+ break;
+ }
+ }
+
+ if (generic2e_via686sb_dev != 0)
+ via686sb_setup(pc, generic2e_via686sb_dev);
+}
+
+int
+generic2e_intr_map(int dev, int fn, int pin)
+{
+ if (dev == generic2e_via686sb_dev) {
+ switch (fn) {
+ case 1: /* PCIIDE */
+ /* will use compat interrupt */
+ break;
+ case 2: /* USB */
+ return BONITO_ISA_IRQ(VIA686_IRQ_PCIB);
+ case 3: /* USB */
+ return BONITO_ISA_IRQ(VIA686_IRQ_PCIC);
+ case 4: /* power management, SMBus */
+ break;
+ case 5: /* Audio */
+ return BONITO_ISA_IRQ(VIA686_IRQ_PCIA);
+ case 6: /* Modem */
+ break;
+ default:
+ break;
+ }
+ } else {
+ return BONITO_DIRECT_IRQ(BONITO_INTR_GPIN +
+ pin - PCI_INTERRUPT_PIN_A);
+ }
+
+ return -1;
+}
+
+/*
+ * ISA model specific routines
+ */
+
+void
+generic2e_isa_attach_hook(struct device *parent, struct device *self,
+ struct isabus_attach_args *iba)
+{
+ set_intr(INTPRI_ISA, CR_INT_3, generic2e_isa_intr);
+ loongson_generic_isa_attach_hook(parent, self, iba);
+}
+
+void *
+generic2e_isa_intr_establish(void *v, int irq, int type, int level,
+ int (*handler)(void *), void *arg, char *name)
+{
+ /* XXX check type, update elcr */
+ return bonito_intr_establish(BONITO_ISA_IRQ(irq), type, level,
+ handler, arg, name);
+}
+
+void
+generic2e_isa_intr_disestablish(void *v, void *ih)
+{
+ /* XXX update elcr */
+ bonito_intr_disestablish(ih);
+}
+
+uint32_t
+generic2e_isa_intr(uint32_t hwpend, struct trap_frame *frame)
+{
+ struct intrhand *ih;
+ uint64_t isr, mask = 0;
+ int rc, irq;
+ uint8_t ocw1, ocw2;
+ extern uint loongson_isaimr;
+
+ for (;;) {
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) =
+ OCW3_SELECT | OCW3_POLL;
+ ocw1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3);
+ if ((ocw1 & OCW3_POLL_PENDING) == 0)
+ break;
+
+ irq = OCW3_POLL_IRQ(ocw1);
+
+ if (irq == 2) /* cascade */ {
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) =
+ OCW3_SELECT | OCW3_POLL;
+ ocw2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3);
+ if (ocw2 & OCW3_POLL_PENDING)
+ irq = OCW3_POLL_IRQ(ocw2);
+ else
+ irq = 2;
+ } else
+ ocw2 = 0;
+
+ /*
+ * Mask the interrupt before servicing it.
+ */
+ isr = 1UL << irq;
+ loongson_set_isa_imr(loongson_isaimr & ~isr);
+
+ /*
+ * If interrupt is spl-masked, wait for splx()
+ * to reenable it when necessary.
+ */
+ if ((isr & BONITO_ISA_MASK(bonito_imask[frame->ipl])) != 0)
+ continue;
+ else
+ mask |= isr;
+
+ rc = 0;
+ for (ih = bonito_intrhand[BONITO_ISA_IRQ(irq)]; ih != NULL;
+ ih = ih->ih_next) {
+ splraise(ih->ih_level);
+
+ if ((*ih->ih_fun)(ih->ih_arg) != 0) {
+ rc = 1;
+ ih->ih_count.ec_count++;
+ }
+
+ __asm__ (".set noreorder\n");
+ curcpu()->ci_ipl = frame->ipl;
+ __asm__ ("sync\n\t.set reorder\n");
+ }
+
+ /* Send a specific EOI to the 8259. */
+ loongson_isa_specific_eoi(irq);
+
+ if (rc == 0) {
+ printf("spurious isa interrupt %d\n", irq);
+#ifdef DEBUG
+ printf("ICU1 %02x ICU2 %02x ipl %d mask %08x"
+ " isaimr %08x\n", ocw1, ocw2, frame->ipl,
+ bonito_imask[frame->ipl], loongson_isaimr);
+#ifdef DDB
+ Debugger();
+#endif
+#endif
+ }
+ }
+
+ /*
+ * Reenable interrupts which have been serviced.
+ */
+ if (mask != 0)
+ loongson_set_isa_imr(loongson_isaimr | mask);
+
+ return mask == 0 ? 0 : hwpend;
+}
+
+/*
+ * Other model specific routines
+ */
+
+void
+generic2e_reset()
+{
+ REGVAL(LOONGSON_GENCFG) &= ~BONITO_GENCFG_CPUSELFRESET;
+ REGVAL(LOONGSON_GENCFG) |= BONITO_GENCFG_CPUSELFRESET;
+ delay(1000000);
+}
+
+void
+generic2e_setup(void)
+{
+#if NCOM > 0
+ const char *envvar;
+ int serial;
+
+ envvar = pmon_getenv("nokbd");
+ serial = envvar != NULL;
+ envvar = pmon_getenv("novga");
+ serial = serial && envvar != NULL;
+
+ if (serial) {
+ comconsiot = &bonito_pci_io_space_tag;
+ comconsaddr = 0x3f8;
+ comconsrate = 115200; /* default PMON console speed */
+ }
+#endif
+}
+
+void
+generic2e_device_register(struct device *dev, void *aux)
+{
+ const char *drvrname = dev->dv_cfdata->cf_driver->cd_name;
+ const char *name = dev->dv_xname;
+
+ if (dev->dv_class != bootdev_class)
+ return;
+
+ /*
+ * The device numbering must match. There's no way
+ * pmon tells us more info. Depending on the usb slot
+ * and hubs used you may be lucky. Also, assume umass/sd for usb
+ * attached devices.
+ */
+ switch (bootdev_class) {
+ case DV_DISK:
+ if (strcmp(drvrname, "wd") == 0 && strcmp(name, bootdev) == 0)
+ bootdv = dev;
+ else {
+ /* XXX this really only works safely for usb0... */
+ if ((strcmp(drvrname, "sd") == 0 ||
+ strcmp(drvrname, "cd") == 0) &&
+ strncmp(bootdev, "usb", 3) == 0 &&
+ strcmp(name + 2, bootdev + 3) == 0)
+ bootdv = dev;
+ }
+ break;
+ case DV_IFNET:
+ /*
+ * This relies on the onboard Ethernet interface being
+ * attached before any other (usb) interface.
+ */
+ bootdv = dev;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Initialize a VIA686 south bridge.
+ *
+ * PMON apparently does not perform enough initialization; one may argue this
+ * could be done with a specific pcib(4) driver, but then no other system
+ * will hopefully need this, so keep it local to the 2E setup code.
+ */
+
+#define VIA686_ISA_ROM_CONTROL 0x40
+#define VIA686_ROM_WRITE_ENABLE 0x00000001
+#define VIA686_NO_ROM_WAIT_STATE 0x00000002
+#define VIA686_EXTEND_ALE 0x00000004
+#define VIA686_IO_RECOVERY_TIME 0x00000008
+#define VIA686_CHIPSET_EXTRA_WAIT_STATES 0x00000010
+#define VIA686_ISA_EXTRA_WAIT_STATES 0x00000020
+#define VIA686_ISA_EXTENDED_BUS_READY 0x00000040
+#define VIA686_ISA_EXTRA_COMMAND_DELAY 0x00000080
+#define VIA686_ISA_REFRESH 0x00000100
+#define VIA686_DOUBLE_DMA_CLOCK 0x00000800
+#define VIA686_PORT_92_FAST_RESET 0x00002000
+#define VIA686_IO_MEDIUM_RECOVERY_TIME 0x00004000
+#define VIA686_KBC_DMA_MISC12 0x44
+#define VIA686_ISA_MASTER_TO_LINE_BUFFER 0x00008000
+#define VIA686_POSTED_MEMORY_WRITE_ENABLE 0x00010000
+#define VIA686_PCI_BURST_INTERRUPTABLE 0x00020000
+#define VIA686_FLUSH_LINE_BUFFER_ON_INTR 0x00200000
+#define VIA686_GATE_INTR 0x00400000
+#define VIA686_PCI_MASTER_WRITE_WAIT_STATE 0x00800000
+#define VIA686_PCI_RESET 0x01000000
+#define VIA686_PCI_READ_DELAY_TRANSACTION_TMO 0x02000000
+#define VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO 0x04000000
+#define VIA686_ICR_SHADOW_ENABLE 0x10000000
+#define VIA686_EISA_PORT_4D0_4D1_ENABLE 0x20000000
+#define VIA686_PCI_DELAY_TRANSACTION_ENABLE 0x40000000
+#define VIA686_CPU_RESET_SOURCE_INIT 0x80000000
+#define VIA686_MISC3_IDE_INTR 0x48
+#define VIA686_IDE_PRIMARY_CHAN_MASK 0x00030000
+#define VIA686_IDE_PRIMARY_CHAN_SHIFT 16
+#define VIA686_IDE_SECONDARY_CHAN_MASK 0x000c0000
+#define VIA686_IDE_SECONDARY_CHAN_SHIFT 18
+#define VIA686_IDE_IRQ14 00
+#define VIA686_IDE_IRQ15 01
+#define VIA686_IDE_IRQ10 02
+#define VIA686_IDE_IRQ11 03
+#define VIA686_IDE_PGNT 0x00800000
+#define VIA686_PNP_DMA_IRQ 0x50
+#define VIA686_DMA_FDC_MASK 0x00000003
+#define VIA686_DMA_FDC_SHIFT 0
+#define VIA686_DMA_LPT_MASK 0x0000000c
+#define VIA686_DMA_LPT_SHIFT 2
+#define VIA686_IRQ_FDC_MASK 0x00000f00
+#define VIA686_IRQ_FDC_SHIFT 8
+#define VIA686_IRQ_LPT_MASK 0x0000f000
+#define VIA686_IRQ_LPT_SHIFT 12
+#define VIA686_IRQ_COM0_MASK 0x000f0000
+#define VIA686_IRQ_COM0_SHIFT 16
+#define VIA686_IRQ_COM1_MASK 0x00f00000
+#define VIA686_IRQ_COM1_SHIFT 20
+#define VIA686_PCI_LEVEL_PNP_IRQ2 0x54
+#define VIA686_PCI_IRQD_EDGE 0x00000001
+#define VIA686_PCI_IRQC_EDGE 0x00000002
+#define VIA686_PCI_IRQB_EDGE 0x00000004
+#define VIA686_PCI_IRQA_EDGE 0x00000008
+#define VIA686_IRQ_PCIA_MASK 0x0000f000
+#define VIA686_IRQ_PCIA_SHIFT 12
+#define VIA686_IRQ_PCIB_MASK 0x000f0000
+#define VIA686_IRQ_PCIB_SHIFT 16
+#define VIA686_IRQ_PCIC_MASK 0x00f00000
+#define VIA686_IRQ_PCIC_SHIFT 20
+#define VIA686_IRQ_PCID_MASK 0xf0000000
+#define VIA686_IRQ_PCID_SHIFT 28
+
+void
+via686sb_setup(pci_chipset_tag_t pc, int dev)
+{
+ pcitag_t tag;
+ pcireg_t reg;
+ uint elcr;
+
+ tag = pci_make_tag(pc, 0, dev, 0);
+
+ /*
+ * Generic ISA bus initialization.
+ */
+
+ reg = pci_conf_read(pc, tag, VIA686_ISA_ROM_CONTROL);
+ reg |= VIA686_IO_RECOVERY_TIME | VIA686_ISA_REFRESH;
+ pci_conf_write(pc, tag, VIA686_ISA_ROM_CONTROL, reg);
+
+ reg = pci_conf_read(pc, tag, VIA686_KBC_DMA_MISC12);
+ reg |= VIA686_CPU_RESET_SOURCE_INIT |
+ VIA686_PCI_DELAY_TRANSACTION_ENABLE |
+ VIA686_EISA_PORT_4D0_4D1_ENABLE |
+ VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO |
+ VIA686_PCI_READ_DELAY_TRANSACTION_TMO |
+ VIA686_PCI_MASTER_WRITE_WAIT_STATE | VIA686_GATE_INTR |
+ VIA686_FLUSH_LINE_BUFFER_ON_INTR;
+ reg &= ~VIA686_ISA_MASTER_TO_LINE_BUFFER;
+ pci_conf_write(pc, tag, VIA686_KBC_DMA_MISC12, reg);
+
+ /*
+ * SuperIO devices interrupt and DMA setup.
+ */
+
+ reg = pci_conf_read(pc, tag, VIA686_MISC3_IDE_INTR);
+ reg &= ~(VIA686_IDE_PRIMARY_CHAN_MASK | VIA686_IDE_SECONDARY_CHAN_MASK);
+ reg |= (VIA686_IDE_IRQ14 << VIA686_IDE_PRIMARY_CHAN_SHIFT);
+ reg |= (VIA686_IDE_IRQ15 << VIA686_IDE_SECONDARY_CHAN_SHIFT);
+ reg |= VIA686_IDE_PGNT;
+ pci_conf_write(pc, tag, VIA686_MISC3_IDE_INTR, reg);
+
+ reg = pci_conf_read(pc, tag, VIA686_PNP_DMA_IRQ);
+ reg &= ~(VIA686_DMA_FDC_MASK | VIA686_DMA_LPT_MASK);
+ reg |= (2 << VIA686_DMA_FDC_SHIFT) | (3 << VIA686_DMA_LPT_SHIFT);
+ reg &= ~(VIA686_IRQ_FDC_MASK | VIA686_IRQ_LPT_MASK);
+ reg |= (6 << VIA686_IRQ_FDC_SHIFT) | (7 << VIA686_IRQ_LPT_SHIFT);
+ reg &= ~(VIA686_IRQ_COM0_MASK | VIA686_IRQ_COM1_MASK);
+ reg |= (4 << VIA686_IRQ_COM0_SHIFT) | (3 << VIA686_IRQ_COM1_SHIFT);
+
+ reg = pci_conf_read(pc, tag, VIA686_PCI_LEVEL_PNP_IRQ2);
+ reg &= ~(VIA686_PCI_IRQA_EDGE | VIA686_PCI_IRQB_EDGE |
+ VIA686_PCI_IRQB_EDGE | VIA686_PCI_IRQD_EDGE);
+ reg &= ~(VIA686_IRQ_PCIA_MASK | VIA686_IRQ_PCIB_MASK |
+ VIA686_IRQ_PCIC_MASK | VIA686_IRQ_PCID_MASK);
+ reg |= (VIA686_IRQ_PCIA << VIA686_IRQ_PCIA_SHIFT) |
+ (VIA686_IRQ_PCIB << VIA686_IRQ_PCIB_SHIFT) |
+ (VIA686_IRQ_PCIC << VIA686_IRQ_PCIC_SHIFT) |
+ (VIA686_IRQ_PCID << VIA686_IRQ_PCID_SHIFT);
+
+ /*
+ * Interrupt controller setup.
+ */
+
+ /* reset; program device, four bytes */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) =
+ ICW1_SELECT | ICW1_IC4;
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0);
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(2);
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086;
+ /* leave interrupts masked */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff;
+ /* special mask mode (if available) */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) =
+ OCW3_SELECT | OCW3_SSMM | OCW3_SMM;
+ /* read IRR by default. */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
+
+ /* reset; program device, four bytes */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW1) =
+ ICW1_SELECT | ICW1_IC4;
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8);
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(2);
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086;
+ /* leave interrupts masked */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff;
+ /* special mask mode (if available) */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) =
+ OCW3_SELECT | OCW3_SSMM | OCW3_SMM;
+ /* read IRR by default. */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
+
+ /* setup ELCR: PCI interrupts are level-triggered. */
+ elcr = (1 << VIA686_IRQ_PCIA) | (1 << VIA686_IRQ_PCIB) |
+ (1 << VIA686_IRQ_PCIC) | (1 << VIA686_IRQ_PCID);
+ REGVAL8(BONITO_PCIIO_BASE + 0x4d0) = (elcr >> 0) & 0xff;
+ REGVAL8(BONITO_PCIIO_BASE + 0x4d1) = (elcr >> 8) & 0xff;
+
+ __asm__ __volatile__ ("sync" ::: "memory");
+
+ /*
+ * Update interrupt information for secondary functions.
+ * Although this information is not used by pci_intr_establish()
+ * because of generic2e_intr_map() behaviour, it seems to be
+ * required to complete proper interrupt routing.
+ */
+
+ tag = pci_make_tag(pc, 0, dev, 2);
+ reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+ reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ reg |= VIA686_IRQ_PCIB << PCI_INTERRUPT_LINE_SHIFT;
+ pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
+
+ tag = pci_make_tag(pc, 0, dev, 3);
+ reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+ reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ reg |= VIA686_IRQ_PCIC << PCI_INTERRUPT_LINE_SHIFT;
+ pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
+
+ tag = pci_make_tag(pc, 0, dev, 5);
+ reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+ reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ reg |= VIA686_IRQ_PCIA << PCI_INTERRUPT_LINE_SHIFT;
+ pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
+}
diff --git a/sys/arch/loongson/loongson/isa_machdep.c b/sys/arch/loongson/loongson/isa_machdep.c
new file mode 100644
index 00000000000..389dac292fc
--- /dev/null
+++ b/sys/arch/loongson/loongson/isa_machdep.c
@@ -0,0 +1,118 @@
+/* $OpenBSD: isa_machdep.c,v 1.1 2010/05/08 21:59:56 miod Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Legacy device support.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/intr.h>
+
+#include <dev/ic/i8259reg.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <loongson/dev/bonitoreg.h>
+#include <loongson/dev/bonitovar.h>
+#include <loongson/dev/bonito_irq.h>
+
+void loongson_set_isa_imr(uint);
+void loongson_isa_splx(int);
+void loongson_isa_setintrmask(int);
+
+uint loongson_isaimr;
+
+void
+loongson_set_isa_imr(uint newimr)
+{
+ uint imr1, imr2;
+
+ imr1 = 0xff & ~newimr;
+ imr1 &= ~(1 << 2); /* enable cascade */
+ imr2 = 0xff & ~(newimr >> 8);
+
+ /*
+ * For some reason, trying to write the same value to the PIC
+ * registers causes an immediate system freeze (at least on the
+ * 2F and CS5536 based Lemote Yeeloong), so we only do this if
+ * the value changes.
+ * Note that interrupts have been disabled by the caller.
+ */
+ if ((newimr ^ loongson_isaimr) & 0xff00)
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1) = imr2;
+ if ((newimr ^ loongson_isaimr) & 0x00ff)
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1) = imr1;
+ loongson_isaimr = newimr;
+}
+
+void
+loongson_isa_specific_eoi(int bit)
+{
+ if (bit & 8) {
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW2) =
+ OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(bit & 7);
+ bit = 2;
+ }
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW2) =
+ OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(bit);
+}
+
+void
+loongson_isa_splx(int newipl)
+{
+ struct cpu_info *ci = curcpu();
+
+ /* Update masks to new ipl. Order highly important! */
+ __asm__ (".set noreorder\n");
+ ci->ci_ipl = newipl;
+ __asm__ ("sync\n\t.set reorder\n");
+ loongson_isa_setintrmask(newipl);
+ /* If we still have softints pending trigger processing. */
+ if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT)
+ setsoftintr0();
+}
+
+void
+loongson_isa_setintrmask(int level)
+{
+ uint64_t active;
+ uint32_t sr;
+
+ active = bonito_intem & ~bonito_imask[level];
+
+ sr = disableintr();
+ bonito_setintrmask(level);
+ loongson_set_isa_imr(BONITO_ISA_MASK(active));
+ setsr(sr);
+}
+
+void
+loongson_generic_isa_attach_hook(struct device *parent, struct device *self,
+ struct isabus_attach_args *iba)
+{
+ loongson_isaimr = 0;
+ /* overrides bonito callback */
+ register_splx_handler(loongson_isa_splx);
+}
diff --git a/sys/arch/loongson/loongson/loongson2_machdep.c b/sys/arch/loongson/loongson/loongson2_machdep.c
index 5b5b623c90d..37eb3734e1d 100644
--- a/sys/arch/loongson/loongson/loongson2_machdep.c
+++ b/sys/arch/loongson/loongson/loongson2_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loongson2_machdep.c,v 1.9 2010/04/21 03:03:26 deraadt Exp $ */
+/* $OpenBSD: loongson2_machdep.c,v 1.10 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -74,20 +74,26 @@ paddr_t loongson_dma_base = 0;
void
loongson2e_setup(u_long memlo, u_long memhi)
{
+ if (memhi > ((DDR_PHYSICAL_SIZE - BONITO_PCIHI_BASE) >> 20)) {
+ pmon_printf("WARNING! %d MB of memory will not be used",
+ memhi - ((DDR_PHYSICAL_SIZE - BONITO_PCIHI_BASE) >> 20));
+ memhi = (DDR_PHYSICAL_SIZE - BONITO_PCIHI_BASE) >> 20;
+ }
+
memlo = atop(memlo << 20);
memhi = atop(memhi << 20);
physmem = memlo + memhi;
- /*
- * Only register the first 256MB of memory.
- * This will be hopefully be revisited once we get our hands
- * on Loongson 2E-based hardware...
- */
-
/* do NOT stomp on exception area */
mem_layout[0].mem_first_page = atop(DDR_PHYSICAL_BASE) + 1;
mem_layout[0].mem_last_page = atop(DDR_PHYSICAL_BASE) + memlo;
+ if (memhi != 0) {
+ mem_layout[1].mem_first_page = atop(BONITO_PCIHI_BASE);
+ mem_layout[1].mem_last_page = atop(BONITO_PCIHI_BASE) +
+ memhi;
+ }
+
loongson_dma_base = PCI_DDR_BASE ^ DDR_PHYSICAL_BASE;
}
@@ -124,7 +130,7 @@ loongson2f_setup(u_long memlo, u_long memhi)
memlo = atop(memlo << 20);
memhi = atop(memhi << 20);
- physmem = atop((vsize_t)physmem << 20);
+ physmem = memlo + memhi;
/*
* PMON configures the system with only the low 256MB of memory
@@ -251,7 +257,7 @@ is_memory_range(paddr_t pa, psize_t len, psize_t limit)
* Allow access to the low 256MB aliased region on 2F systems,
* if we are accessing memory at 2GB onwards.
*/
- if (pa < 0x10000000) {
+ if (pa < 0x10000000 && loongson_ver == 0x2f) {
fp += mem_layout[0].mem_first_page - 1;
lp += mem_layout[0].mem_first_page - 1;
}
diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c
index 49e987af86a..46ac7d6e155 100644
--- a/sys/arch/loongson/loongson/machdep.c
+++ b/sys/arch/loongson/loongson/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.18 2010/04/27 04:26:20 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.19 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -77,9 +77,6 @@
#include <mips64/archtype.h>
-#include <loongson/dev/bonitoreg.h>
-#include <loongson/dev/bonitovar.h>
-
/* The following is used externally (sysctl_hw) */
char machine[] = MACHINE; /* Machine "architecture" */
char cpu_model[30];
@@ -110,6 +107,7 @@ int kbd_reset;
const struct platform *sys_platform;
struct cpu_hwinfo bootcpu_hwinfo;
+uint loongson_ver;
/* Pointers to the start and end of the symbol table. */
caddr_t ssym;
@@ -155,6 +153,7 @@ struct bonito_flavour {
extern const struct platform fuloong_platform;
extern const struct platform gdium_platform;
+extern const struct platform generic2e_platform;
extern const struct platform lynloong_platform;
extern const struct platform yeeloong_platform;
@@ -183,7 +182,7 @@ vaddr_t
mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv,
char *boot_esym)
{
- uint prid, loongson_ver;
+ uint prid;
u_long memlo, memhi, cpuspeed;
vaddr_t xtlb_handler;
const char *envvar;
@@ -280,20 +279,29 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv,
envvar = pmon_getenv("Version");
if (envvar == NULL) {
- pmon_printf("Unable to figure out model!\n");
- goto unsupported;
- }
-
- for (f = bonito_flavours; f->prefix != NULL; f++)
- if (strncmp(envvar, f->prefix, strlen(f->prefix)) == 0) {
- sys_platform = f->platform;
- break;
+ /*
+ * If this is a 2E system, use the generic code and hope
+ * for the best.
+ */
+ if (loongson_ver == 0x2e) {
+ sys_platform = &generic2e_platform;
+ } else {
+ pmon_printf("Unable to figure out model!\n");
+ goto unsupported;
}
+ } else {
+ for (f = bonito_flavours; f->prefix != NULL; f++)
+ if (strncmp(envvar, f->prefix, strlen(f->prefix)) ==
+ 0) {
+ sys_platform = f->platform;
+ break;
+ }
- if (sys_platform == NULL) {
- pmon_printf("This kernel doesn't support model \"%s\".\n",
- envvar);
- goto unsupported;
+ if (sys_platform == NULL) {
+ pmon_printf("This kernel doesn't support model \"%s\"."
+ "\n", envvar);
+ goto unsupported;
+ }
}
hw_vendor = sys_platform->vendor;
diff --git a/sys/arch/loongson/loongson/pciide_machdep.c b/sys/arch/loongson/loongson/pciide_machdep.c
index 267b44f1941..6aa05b32427 100644
--- a/sys/arch/loongson/loongson/pciide_machdep.c
+++ b/sys/arch/loongson/loongson/pciide_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide_machdep.c,v 1.1 2009/11/25 18:56:34 miod Exp $ */
+/* $OpenBSD: pciide_machdep.c,v 1.2 2010/05/08 21:59:56 miod Exp $ */
/* $NetBSD: pciide_machdep.c,v 1.2 1999/02/19 18:01:27 mycroft Exp $ */
/*
@@ -50,6 +50,8 @@
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>
+#include <machine/autoconf.h>
+
#include <dev/isa/isavar.h>
void *
@@ -59,9 +61,12 @@ pciide_machdep_compat_intr_establish(struct device *dev,
int irq;
void *cookie;
- irq = PCIIDE_COMPAT_IRQ(chan);
- cookie = isa_intr_establish(NULL, irq, IST_EDGE, IPL_BIO, func, arg,
- dev->dv_xname);
+ if (sys_platform->isa_chipset != NULL) {
+ irq = PCIIDE_COMPAT_IRQ(chan);
+ cookie = isa_intr_establish(sys_platform->isa_chipset,
+ irq, IST_EDGE, IPL_BIO, func, arg, dev->dv_xname);
+ } else
+ cookie = NULL;
return (cookie);
}
@@ -69,5 +74,6 @@ pciide_machdep_compat_intr_establish(struct device *dev,
void
pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
{
- isa_intr_disestablish(NULL, cookie);
+ if (sys_platform->isa_chipset != NULL)
+ isa_intr_disestablish(sys_platform->isa_chipset, cookie);
}
diff --git a/sys/arch/loongson/loongson/wscons_machdep.c b/sys/arch/loongson/loongson/wscons_machdep.c
index a28b2f89d52..219c93f34a3 100644
--- a/sys/arch/loongson/loongson/wscons_machdep.c
+++ b/sys/arch/loongson/loongson/wscons_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_machdep.c,v 1.6 2010/02/28 22:32:50 miod Exp $ */
+/* $OpenBSD: wscons_machdep.c,v 1.7 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2010 Miodrag Vallat.
@@ -58,6 +58,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/pci/vga_pcivar.h>
#include "wsdisplay.h"
#if NWSDISPLAY > 0
@@ -67,6 +68,7 @@
extern int sisfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
#include "smfb.h"
extern int smfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
+#include "vga.h"
#include "pckbc.h"
#if NPCKBC > 0
@@ -88,7 +90,11 @@ cons_decl(ws);
void
wscnprobe(struct consdev *cp)
{
- int maj;
+ pcitag_t tag;
+ pcireg_t id, class;
+ int maj, dev;
+
+ cp->cn_pri = CN_DEAD;
/* Locate the major number. */
for (maj = 0; maj < nchrdev; maj++) {
@@ -98,11 +104,27 @@ wscnprobe(struct consdev *cp)
if (maj == nchrdev) {
/* We are not in cdevsw[], give up. */
- panic("wsdisplay is not in cdevsw[]");
+ return;
}
- cp->cn_dev = makedev(maj, 0);
- cp->cn_pri = CN_MIDPRI;
+ /*
+ * Look for a suitable video device.
+ */
+
+ for (dev = 0; dev < 32; dev++) {
+ tag = pci_make_tag_early(0, dev, 0);
+ id = pci_conf_read_early(tag, PCI_ID_REG);
+ if (id == 0 || PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+
+ class = pci_conf_read_early(tag, PCI_CLASS_REG);
+ if (!DEVICE_IS_VGA_PCI(class))
+ continue;
+
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_MIDPRI;
+ break;
+ }
}
void
@@ -114,12 +136,15 @@ static int initted;
int dev, rc;
extern struct mips_bus_space bonito_pci_io_space_tag;
extern struct mips_bus_space bonito_pci_mem_space_tag;
+ extern struct consdev pmoncons;
if (initted)
return;
initted = 1;
+ cn_tab = &pmoncons; /* to be able to panic */
+
/*
* Look for a suitable video device.
*/
@@ -131,7 +156,7 @@ static int initted;
continue;
class = pci_conf_read_early(tag, PCI_CLASS_REG);
- if (PCI_CLASS(class) != PCI_CLASS_DISPLAY)
+ if (!DEVICE_IS_VGA_PCI(class))
continue;
/*
@@ -139,20 +164,33 @@ static int initted;
*/
rc = ENXIO;
+
+ /* bitmapped frame buffer won't be of PREHISTORIC class */
+ if (PCI_CLASS(class) == PCI_CLASS_DISPLAY) {
#if NSISFB > 0
- if (rc != 0)
- rc = sisfb_cnattach(&bonito_pci_mem_space_tag,
- &bonito_pci_io_space_tag, tag, id);
+ if (rc != 0)
+ rc = sisfb_cnattach(&bonito_pci_mem_space_tag,
+ &bonito_pci_io_space_tag, tag, id);
#endif
#if NSMFB > 0
- if (rc != 0)
- rc = smfb_cnattach(&bonito_pci_mem_space_tag,
- &bonito_pci_io_space_tag, tag, id);
+ if (rc != 0)
+ rc = smfb_cnattach(&bonito_pci_mem_space_tag,
+ &bonito_pci_io_space_tag, tag, id);
+#endif
+ }
+#if NVGA > 0
+ if (rc != 0) {
+ /* thanks $DEITY the pci_chipset_tag_t arg is ignored */
+ rc = vga_pci_cnattach(&bonito_pci_io_space_tag,
+ &bonito_pci_mem_space_tag, NULL, 0, dev, 0);
+ }
#endif
if (rc == 0)
goto setup_kbd;
}
+ cn_tab = cp;
+
/* no glass console... */
return;
@@ -165,21 +203,16 @@ setup_kbd:
rc = ENXIO;
#if NPCKBC > 0
- switch (sys_platform->system_type) {
- default:
- /* no pckbc or no legacy hardware */
- break;
- case LOONGSON_YEELOONG:
- if (rc != 0)
- rc = pckbc_cnattach(&bonito_pci_io_space_tag, IO_KBD,
- KBCMDP, PCKBC_KBD_SLOT, 0);
- break;
- }
+ if (rc != 0)
+ rc = pckbc_cnattach(&bonito_pci_io_space_tag, IO_KBD,
+ KBCMDP, PCKBC_KBD_SLOT, 0);
#endif
#if NUKBD > 0
if (rc != 0)
rc = ukbd_cnattach();
#endif
+
+ cn_tab = cp;
}
void
@@ -193,7 +226,7 @@ wscnputc(dev_t dev, int i)
int
wscngetc(dev_t dev)
{
-#if NPCKBD > 0
+#if NPCKBD > 0 || NUKBD > 0
int c;
wskbd_cnpollc(dev, 1);
@@ -209,7 +242,7 @@ wscngetc(dev_t dev)
void
wscnpollc(dev_t dev, int on)
{
-#if NPCKBD > 0
+#if NPCKBD > 0 || NUKBD > 0
wskbd_cnpollc(dev, on);
#endif
}
diff --git a/sys/arch/loongson/loongson/yeeloong_machdep.c b/sys/arch/loongson/loongson/yeeloong_machdep.c
index 5d25381f039..cf99f774400 100644
--- a/sys/arch/loongson/loongson/yeeloong_machdep.c
+++ b/sys/arch/loongson/loongson/yeeloong_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yeeloong_machdep.c,v 1.11 2010/03/02 20:54:51 miod Exp $ */
+/* $OpenBSD: yeeloong_machdep.c,v 1.12 2010/05/08 21:59:56 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -30,8 +30,10 @@
#include <machine/pmon.h>
#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <loongson/dev/bonitoreg.h>
@@ -48,15 +50,26 @@
extern struct mips_bus_space bonito_pci_io_space_tag;
#endif
-void lemote_attach_hook(pci_chipset_tag_t);
-void lemote_device_register(struct device *, void *);
-int lemote_intr_map(int, int, int);
-void lemote_reset(void);
+void lemote_device_register(struct device *, void *);
+void lemote_reset(void);
-void fuloong_powerdown(void);
-void fuloong_setup(void);
+void fuloong_powerdown(void);
+void fuloong_setup(void);
-void yeeloong_powerdown(void);
+void yeeloong_powerdown(void);
+
+void lemote_pci_attach_hook(pci_chipset_tag_t);
+int lemote_intr_map(int, int, int);
+
+void lemote_isa_attach_hook(struct device *, struct device *,
+ struct isabus_attach_args *);
+void *lemote_isa_intr_establish(void *, int, int, int, int (*)(void *),
+ void *, char *);
+void lemote_isa_intr_disestablish(void *, void *);
+
+uint lemote_get_isa_imr(void);
+uint lemote_get_isa_isr(void);
+uint32_t lemote_isa_intr(uint32_t, struct trap_frame *);
const struct bonito_config lemote_bonito = {
.bc_adbase = 11,
@@ -69,9 +82,7 @@ const struct bonito_config lemote_bonito = {
LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR |
LOONGSON_INTRMASK_INT0 | LOONGSON_INTRMASK_INT1,
- .bc_legacy_pic = 1,
-
- .bc_attach_hook = lemote_attach_hook,
+ .bc_attach_hook = lemote_pci_attach_hook,
.bc_intr_map = lemote_intr_map
};
@@ -129,12 +140,21 @@ const struct legacy_io_range yeeloong_legacy_ranges[] = {
{ 0 }
};
+struct mips_isa_chipset lemote_isa_chipset = {
+ .ic_v = NULL,
+
+ .ic_attach_hook = lemote_isa_attach_hook,
+ .ic_intr_establish = lemote_isa_intr_establish,
+ .ic_intr_disestablish = lemote_isa_intr_disestablish
+};
+
const struct platform fuloong_platform = {
.system_type = LOONGSON_FULOONG,
.vendor = "Lemote",
.product = "Fuloong",
.bonito_config = &lemote_bonito,
+ .isa_chipset = &lemote_isa_chipset,
.legacy_io_ranges = fuloong_legacy_ranges,
.setup = fuloong_setup,
@@ -150,6 +170,7 @@ const struct platform lynloong_platform = {
.product = "Lynloong",
.bonito_config = &lemote_bonito,
+ .isa_chipset = &lemote_isa_chipset,
.legacy_io_ranges = lynloong_legacy_ranges,
.setup = fuloong_setup,
@@ -165,6 +186,7 @@ const struct platform yeeloong_platform = {
.product = "Yeeloong",
.bonito_config = &lemote_bonito,
+ .isa_chipset = &lemote_isa_chipset,
.legacy_io_ranges = yeeloong_legacy_ranges,
.setup = NULL,
@@ -174,8 +196,12 @@ const struct platform yeeloong_platform = {
.reset = lemote_reset
};
+/*
+ * PCI model specific routines
+ */
+
void
-lemote_attach_hook(pci_chipset_tag_t pc)
+lemote_pci_attach_hook(pci_chipset_tag_t pc)
{
pcireg_t id;
pcitag_t tag;
@@ -233,6 +259,163 @@ lemote_intr_map(int dev, int fn, int pin)
return -1;
}
+/*
+ * ISA model specific routines
+ */
+
+void
+lemote_isa_attach_hook(struct device *parent, struct device *self,
+ struct isabus_attach_args *iba)
+{
+ set_intr(INTPRI_ISA, CR_INT_0, lemote_isa_intr);
+
+ /* disable all isa interrupt sources */
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1) = 0xff;
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 2) = 0xff;
+
+ loongson_generic_isa_attach_hook(parent, self, iba);
+}
+
+void *
+lemote_isa_intr_establish(void *v, int irq, int type, int level,
+ int (*handler)(void *), void *arg, char *name)
+{
+ return bonito_intr_establish(BONITO_ISA_IRQ(irq), type, level,
+ handler, arg, name);
+}
+
+void
+lemote_isa_intr_disestablish(void *v, void *ih)
+{
+ bonito_intr_disestablish(ih);
+}
+
+/*
+ * Legacy (ISA) interrupt handling
+ */
+
+/*
+ * Process legacy interrupts.
+ *
+ * XXX On 2F, ISA interrupts only occur on LOONGSON_INTR_INT0, but since
+ * XXX the other LOONGSON_INTR_INT# are unmaskable, bad things will happen
+ * XXX if they ever are triggered...
+ */
+uint32_t
+lemote_isa_intr(uint32_t hwpend, struct trap_frame *frame)
+{
+ uint64_t imr, isr, mask;
+ int bit;
+ struct intrhand *ih;
+ int rc;
+
+ isr = lemote_get_isa_isr();
+ imr = lemote_get_isa_imr();
+
+ isr &= imr;
+ isr &= ~(1 << 2); /* cascade */
+#ifdef DEBUG
+ printf("isa interrupt: imr %04x isr %04x\n", imr, isr);
+#endif
+ if (isr == 0)
+ return 0; /* not for us */
+
+ /*
+ * Mask all pending interrupts.
+ */
+
+ loongson_set_isa_imr(imr & ~isr);
+
+ /*
+ * If interrupts are spl-masked, mask them and wait for splx()
+ * to reenable them when necessary.
+ */
+ if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) {
+ isr &= ~mask;
+ imr &= ~mask;
+ }
+
+ /*
+ * Now process allowed interrupts.
+ */
+ if (isr != 0) {
+ int lvl, bitno;
+ uint64_t tmpisr;
+
+ /* Service higher level interrupts first */
+ bit = BONITO_NISA - 1;
+ for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
+ tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^
+ bonito_imask[lvl - 1]);
+ if (tmpisr == 0)
+ continue;
+ for (bitno = bit, mask = 1UL << bitno; mask != 0;
+ bitno--, mask >>= 1) {
+ if ((tmpisr & mask) == 0)
+ continue;
+
+ rc = 0;
+ for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)];
+ ih != NULL; ih = ih->ih_next) {
+ splraise(ih->ih_level);
+ if ((*ih->ih_fun)(ih->ih_arg) != 0) {
+ rc = 1;
+ ih->ih_count.ec_count++;
+ }
+ __asm__ (".set noreorder\n");
+ curcpu()->ci_ipl = frame->ipl;
+ __asm__ ("sync\n\t.set reorder\n");
+ }
+ if (rc == 0)
+ printf("spurious isa interrupt %d\n",
+ bitno);
+
+ loongson_isa_specific_eoi(bitno);
+
+ if ((isr ^= mask) == 0)
+ goto done;
+ if ((tmpisr ^= mask) == 0)
+ break;
+ }
+ }
+done:
+
+ /*
+ * Reenable interrupts which have been serviced.
+ */
+ loongson_set_isa_imr(imr);
+ }
+
+ return hwpend;
+}
+
+uint
+lemote_get_isa_imr()
+{
+ uint imr1, imr2;
+
+ imr1 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1);
+ imr1 &= ~(1 << 2); /* hide cascade */
+ imr2 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1);
+
+ return (imr2 << 8) | imr1;
+}
+
+uint
+lemote_get_isa_isr()
+{
+ uint isr1, isr2;
+
+ isr1 = 0xff & REGVAL8(BONITO_PCIIO_BASE + IO_ICU1);
+ isr2 = 0xff & REGVAL8(BONITO_PCIIO_BASE + IO_ICU2);
+
+ return (isr2 << 8) | isr1;
+}
+
+/*
+ * Other model specific routines
+ */
+
void
fuloong_powerdown()
{