summaryrefslogtreecommitdiff
path: root/sys/arch/i386/pci
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2005-10-20 15:09:32 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2005-10-20 15:09:32 +0000
commit9508beba0f160c758f20577acb1eed33718fce2a (patch)
treef0ba9fdd3d81e7d0c2cfff234ee47cb5ddf25e29 /sys/arch/i386/pci
parent37410dba19e5062b1f6cb32a928b7f3a43ce5cc7 (diff)
add 8237 support and repair 8231 that was confused very bad; lots of testing help by henning@
Diffstat (limited to 'sys/arch/i386/pci')
-rw-r--r--sys/arch/i386/pci/pci_intr_fixup.c4
-rw-r--r--sys/arch/i386/pci/via8231.c113
-rw-r--r--sys/arch/i386/pci/via8231reg.h50
3 files changed, 112 insertions, 55 deletions
diff --git a/sys/arch/i386/pci/pci_intr_fixup.c b/sys/arch/i386/pci/pci_intr_fixup.c
index 82716b98715..63c034aa19c 100644
--- a/sys/arch/i386/pci/pci_intr_fixup.c
+++ b/sys/arch/i386/pci/pci_intr_fixup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_intr_fixup.c,v 1.41 2005/10/17 19:17:24 mickey Exp $ */
+/* $OpenBSD: pci_intr_fixup.c,v 1.42 2005/10/20 15:09:31 mickey Exp $ */
/* $NetBSD: pci_intr_fixup.c,v 1.10 2000/08/10 21:18:27 soda Exp $ */
/*
@@ -182,6 +182,8 @@ const struct pciintr_icu_table {
{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8231_ISA,
via8231_init },
+ { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237_ISA,
+ via8231_init },
{ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503,
sis85c503_init },
diff --git a/sys/arch/i386/pci/via8231.c b/sys/arch/i386/pci/via8231.c
index 62f52919f55..110519c149a 100644
--- a/sys/arch/i386/pci/via8231.c
+++ b/sys/arch/i386/pci/via8231.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: via8231.c,v 1.1 2003/07/30 05:26:33 mickey Exp $ */
+/* $OpenBSD: via8231.c,v 1.2 2005/10/20 15:09:31 mickey Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -36,8 +36,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-
/*
+ * Copyright (c) 2005, by Michael Shalayeff
* Copyright (c) 2003, by Matthew Gream
* Copyright (c) 1999, by UCHIYAMA Yasushi
* All rights reserved.
@@ -65,7 +65,9 @@
/*
* Support for the VIA Technologies Inc. VIA8231 PCI to ISA Bridge
- * Based upon documentation: VIA VT8231 South Bridge, Revision 1.85 (March 11, 2002), pg 73
+ * Based upon documentation:
+ * 1. VIA VT8231 South Bridge, Revision 1.85 (March 11, 2002), pg 73
+ * 2. VIA VT8237R South Bridge, Revision 2.06 (December 15, 2004), pg 100
* Derived from amd756.c
*/
@@ -89,6 +91,8 @@ struct via8231_handle {
bus_space_handle_t ph_regs_ioh;
pci_chipset_tag_t ph_pc;
pcitag_t ph_tag;
+ int flags;
+#define VT8237 0x0001
};
int via8231_getclink(pciintr_icu_handle_t, int, int *);
@@ -112,12 +116,7 @@ struct mask_shft_pair {
int mask;
int shft;
};
-static const struct mask_shft_pair via8231_trigger_cnfg[VIA8231_LINK_MAX+1] = {
- { (1<<3), 3 }, /*PINTA#*/
- { (1<<2), 2 }, /*PINTB#*/
- { (1<<1), 1 }, /*PINTC#*/
- { (1<<0), 0 } /*PINTD#*/
-};
+
static const struct mask_shft_pair via8231_routing_cnfg[VIA8231_LINK_MAX+1] = {
{ 0x0f, 0+4 }, /*PINTA#*/
{ 0x0f, 8+0 }, /*PINTB#*/
@@ -126,23 +125,19 @@ static const struct mask_shft_pair via8231_routing_cnfg[VIA8231_LINK_MAX+1] = {
};
#define VIA8231_GET_TRIGGER_CNFG(reg, pirq) \
- ((reg & via8231_trigger_cnfg[pirq].mask) >> \
- via8231_trigger_cnfg[pirq].shft)
-
-#define VIA8231_SET_TRIGGER_CNFG(reg, pirq, cfg) \
- reg = (reg & ~via8231_trigger_cnfg[pirq].mask) | \
- ((cfg << via8231_trigger_cnfg[pirq].shft) & \
- via8231_trigger_cnfg[pirq].mask)
+ ((reg) & (1 << (3 - (clink & 3))))
+#define VIA8231_SET_TRIGGER_CNFG(reg, clink, cfg) \
+ (((reg) & ~(1 << (3 - (clink & 3)))) | ((cfg) << (3 - (clink & 3))))
#define VIA8231_GET_ROUTING_CNFG(reg, pirq) \
- (((reg) & via8231_routing_cnfg[pirq].mask) >> \
- via8231_routing_cnfg[pirq].shft)
+ (((reg) >> via8231_routing_cnfg[(pirq)].shft) & \
+ via8231_routing_cnfg[(pirq)].mask)
#define VIA8231_SET_ROUTING_CNFG(reg, pirq, cfg) \
- reg = (reg & ~via8231_routing_cnfg[pirq].mask) | \
- ((cfg << via8231_routing_cnfg[pirq].shft) & \
- via8231_routing_cnfg[pirq].mask)
-
+ (((reg) & ~(via8231_routing_cnfg[(pirq)].mask << \
+ via8231_routing_cnfg[(pirq)].shft)) | \
+ (((cfg) & via8231_routing_cnfg[(pirq)].mask) << \
+ via8231_routing_cnfg[(pirq)].shft))
int
via8231_init(pc, iot, tag, ptagp, phandp)
@@ -153,6 +148,7 @@ via8231_init(pc, iot, tag, ptagp, phandp)
pciintr_icu_handle_t *phandp;
{
struct via8231_handle *ph;
+ pcireg_t id;
ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
if (ph == NULL)
@@ -161,6 +157,9 @@ via8231_init(pc, iot, tag, ptagp, phandp)
ph->ph_iot = iot;
ph->ph_pc = pc;
ph->ph_tag = tag;
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ ph->flags = PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
+ PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT8231_ISA? 0 : VT8237;
*ptagp = &via8231_pci_icu;
*phandp = ph;
@@ -177,7 +176,12 @@ via8231_getclink(v, link, clinkp)
pciintr_icu_handle_t v;
int link, *clinkp;
{
- if (VIA8231_LINK_LEGAL(link - 1) == 0)
+ struct via8231_handle *ph = v;
+
+ if ((ph->flags & VT8237) && !VIA8237_LINK_LEGAL(link - 1))
+ return (1);
+
+ if (!(ph->flags & VT8237) && !VIA8231_LINK_LEGAL(link - 1))
return (1);
*clinkp = link - 1;
@@ -192,11 +196,17 @@ via8231_get_intr(v, clink, irqp)
struct via8231_handle *ph = v;
int reg, val;
- if (VIA8231_LINK_LEGAL(clink) == 0)
+ if (VIA8237_LINK_LEGAL(clink) == 0)
return (1);
- reg = VIA8231_GET_ROUTING(ph);
- val = VIA8231_GET_ROUTING_CNFG(reg, clink);
+ if (VIA8231_LINK_LEGAL(clink)) {
+ reg = VIA8231_GET_ROUTING(ph);
+ val = VIA8231_GET_ROUTING_CNFG(reg, clink);
+ } else {
+ reg = VIA8237_GET_ROUTING(ph);
+ val = (reg >> ((clink & 3) * 4)) & 0xf;
+ }
+
*irqp = (val == VIA8231_ROUTING_CNFG_DISABLED) ?
I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
@@ -211,7 +221,7 @@ via8231_set_intr(v, clink, irq)
struct via8231_handle *ph = v;
int reg;
- if (VIA8231_LINK_LEGAL(clink) == 0 || VIA8231_PIRQ_LEGAL(irq) == 0)
+ if (VIA8237_LINK_LEGAL(clink) == 0 || VIA8231_PIRQ_LEGAL(irq) == 0)
return (1);
#ifdef VIA8231_DEBUG
@@ -219,9 +229,15 @@ via8231_set_intr(v, clink, irq)
via8231_pir_dump("via8231_set_intr: ", ph);
#endif
- reg = VIA8231_GET_ROUTING(ph);
- VIA8231_SET_ROUTING_CNFG(reg, clink, irq);
- VIA8231_SET_ROUTING(ph, reg);
+ if (VIA8231_LINK_LEGAL(clink)) {
+ reg = VIA8231_GET_ROUTING(ph);
+ VIA8231_SET_ROUTING(ph,
+ VIA8231_SET_ROUTING_CNFG(reg, clink, irq));
+ } else {
+ reg = VIA8237_GET_ROUTING(ph);
+ VIA8237_SET_ROUTING(ph, (reg & ~(0xf << (clink & 3))) |
+ ((irq & 0xf) << (clink & 3)));
+ }
return (0);
}
@@ -232,25 +248,20 @@ via8231_get_trigger(v, irq, triggerp)
int irq, *triggerp;
{
struct via8231_handle *ph = v;
- int reg, clink, pciirq;
+ int reg, clink, max, pciirq;
if (VIA8231_PIRQ_LEGAL(irq) == 0)
return (1);
- for (clink = 0; clink <= VIA8231_LINK_MAX; clink++) {
+ max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
+ for (clink = 0; clink <= max; clink++) {
via8231_get_intr(v, clink, &pciirq);
if (pciirq == irq) {
- reg = VIA8231_GET_TRIGGER(ph);
- switch (VIA8231_GET_TRIGGER_CNFG(reg, clink)) {
- case VIA8231_TRIGGER_CNFG_LEVEL:
- *triggerp = IST_LEVEL;
- break;
- case VIA8231_TRIGGER_CNFG_EDGE:
- *triggerp = IST_EDGE;
- break;
- default:
- return (1);
- }
+ reg = VIA8231_LINK_LEGAL(clink)?
+ VIA8231_GET_TRIGGER(ph):
+ VIA8237_GET_TRIGGER(ph);
+ *triggerp = VIA8231_GET_TRIGGER_CNFG(reg, clink)?
+ IST_EDGE : IST_LEVEL;
return (0);
}
}
@@ -264,7 +275,7 @@ via8231_set_trigger(v, irq, trigger)
int irq, trigger;
{
struct via8231_handle *ph = v;
- int reg, clink, pciirq;
+ int reg, clink, max, pciirq;
if (VIA8231_PIRQ_LEGAL(irq) == 0 || VIA8231_TRIG_LEGAL(trigger) == 0)
return (1);
@@ -274,23 +285,29 @@ via8231_set_trigger(v, irq, trigger)
via8231_pir_dump("via8231_set_trig: ", ph);
#endif
+ max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
for (clink = 0; clink <= VIA8231_LINK_MAX; clink++) {
via8231_get_intr(v, clink, &pciirq);
if (pciirq == irq) {
- reg = VIA8231_GET_ROUTING(ph);
+ reg = VIA8231_LINK_LEGAL(clink)?
+ VIA8231_GET_TRIGGER(ph):
+ VIA8237_GET_TRIGGER(ph);
switch (trigger) {
case IST_LEVEL:
- VIA8231_SET_TRIGGER_CNFG(reg, clink,
+ reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
VIA8231_TRIGGER_CNFG_LEVEL);
break;
case IST_EDGE:
- VIA8231_SET_TRIGGER_CNFG(reg, clink,
+ reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
VIA8231_TRIGGER_CNFG_EDGE);
break;
default:
return (1);
}
- VIA8231_SET_ROUTING(ph, reg);
+ if (VIA8231_LINK_LEGAL(clink))
+ VIA8231_SET_ROUTING(ph, reg);
+ else
+ VIA8237_SET_ROUTING(ph, reg);
return (0);
}
}
diff --git a/sys/arch/i386/pci/via8231reg.h b/sys/arch/i386/pci/via8231reg.h
index d8f563fab40..c7cbd7cdba8 100644
--- a/sys/arch/i386/pci/via8231reg.h
+++ b/sys/arch/i386/pci/via8231reg.h
@@ -1,6 +1,7 @@
-/* $OpenBSD: via8231reg.h,v 1.1 2003/07/30 05:26:33 mickey Exp $ */
+/* $OpenBSD: via8231reg.h,v 1.2 2005/10/20 15:09:31 mickey Exp $ */
/*
+ * Copyright (c) 2005, by Michael Shalayeff
* Copyright (c) 2003, by Matthew Gream
* Copyright (c) 1999, by UCHIYAMA Yasushi
* All rights reserved.
@@ -50,49 +51,86 @@
* (0x57)
* bits 7-4: PINTD# Routing
* bits 3-0: reserved
+ * PIRQ Select register. (0x44 - 0x47)
+ * (0x44)
+ * bits 7-4: PINTF# Routing
+ * bits 3-0: PINTE# Routing
+ * (0x45)
+ * bits 7-4: PINTH# Routing
+ * bits 3-0: PINTG# Routing
+ * (0x46)
+ * bit 4: EFGH/ABCD share (1 -- use above mappings)
+ * bit 3: Edge Triggered Interrupt Select for PCI Interrupt H
+ * bit 2: Edge Triggered Interrupt Select for PCI Interrupt G
+ * bit 1: Edge Triggered Interrupt Select for PCI Interrupt F
+ * bit 0: Edge Triggered Interrupt Select for PCI Interrupt E
+ *
* 0000: Disabled 0100: IRQ4 1000: Reserved 1100: IRQ12
* 0001: IRQ1 0101: IRQ5 1001: IRQ9 1101: Reserved
* 0010: Reserved 0110: IRQ6 1010: IRQ10 1110: IRQ14
* 0011: IRQ3 0111: IRQ7 1011: IRQ11 1111: IRQ15
*/
-#define VIA8231_CFG_PIR 0x54
-
+#define VIA8231_CFG_PIR 0x54
+#define VIA8237_CFG_PIR 0x44
#define VIA8231_TRIGGER_CNFG_MASK 0x000000ff
#define VIA8231_TRIGGER_CNFG_SHFT 0
+#define VIA8237_TRIGGER_CNFG_MASK 0x00ff0000
+#define VIA8237_TRIGGER_CNFG_SHFT 16
#define VIA8231_TRIGGER_CNFG_LEVEL 0
#define VIA8231_TRIGGER_CNFG_EDGE 1
+#define VIA8237_TRIGGER_CNFG_ENA 0x100000
#define VIA8231_GET_TRIGGER(ph) \
((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR) \
- & VIA8231_TRIGGER_CNFG_MASK) >> VIA8231_TRIGGER_CNFG_SHFT)
+ & VIA8231_TRIGGER_CNFG_MASK) >> VIA8231_TRIGGER_CNFG_SHFT)
+#define VIA8237_GET_TRIGGER(ph) \
+ ((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR) \
+ & VIA8237_TRIGGER_CNFG_MASK) >> VIA8237_TRIGGER_CNFG_SHFT)
#define VIA8231_SET_TRIGGER(ph, n) \
pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR, \
(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR) \
& ~VIA8231_TRIGGER_CNFG_MASK) | ((n) << VIA8231_TRIGGER_CNFG_SHFT))
+#define VIA8237_SET_TRIGGER(ph, n) \
+ pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR, \
+ (pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR) \
+ & ~VIA8237_TRIGGER_CNFG_MASK) | ((n) << VIA8237_TRIGGER_CNFG_SHFT))
#define VIA8231_ROUTING_CNFG_MASK 0xffffff00
#define VIA8231_ROUTING_CNFG_SHFT 8 /* skip 0x54 triggers */
#define VIA8231_ROUTING_CNFG_DISABLED 0
+#define VIA8237_ROUTING_CNFG_MASK 0xffff
+#define VIA8237_ROUTING_CNFG_SHFT 0
#define VIA8231_GET_ROUTING(ph) \
((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR) \
- & VIA8231_ROUTING_CNFG_MASK) >> VIA8231_ROUTING_CNFG_SHFT)
+ & VIA8237_ROUTING_CNFG_MASK) >> VIA8231_ROUTING_CNFG_SHFT)
+#define VIA8237_GET_ROUTING(ph) \
+ ((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR) \
+ & VIA8231_ROUTING_CNFG_MASK) >> VIA8237_ROUTING_CNFG_SHFT)
#define VIA8231_SET_ROUTING(ph, n) \
pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR, \
(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR) \
& ~VIA8231_ROUTING_CNFG_MASK) | ((n) << VIA8231_ROUTING_CNFG_SHFT))
+#define VIA8237_SET_ROUTING(ph, n) \
+ pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR, \
+ (pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR) \
+ & ~VIA8237_ROUTING_CNFG_MASK) | \
+ ((n) << VIA8237_ROUTING_CNFG_SHFT) | VIA8237_TRIGGER_CNFG_ENA)
#define VIA8231_PIRQ_MASK 0xdefa
#define VIA8231_PIRQ_LEGAL(irq) \
- ((irq) >= 0 && (irq) <= 15 && ((1 << (irq)) & VIA8231_PIRQ_MASK) != 0)
+ ((irq) >= 0 && (irq) <= 15 && ((1 << (irq)) & VIA8231_PIRQ_MASK))
#define VIA8231_LINK_MAX 3
+#define VIA8237_LINK_MAX 7
#define VIA8231_LINK_LEGAL(link) \
((link) >= 0 && (link) <= VIA8231_LINK_MAX)
+#define VIA8237_LINK_LEGAL(link) \
+ ((link) >= 0 && (link) <= VIA8237_LINK_MAX)
#define VIA8231_TRIG_LEGAL(trig) \
((trig) == IST_LEVEL || (trig) == IST_EDGE)