summaryrefslogtreecommitdiff
path: root/sys/arch/i386/pci/via8231.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386/pci/via8231.c')
-rw-r--r--sys/arch/i386/pci/via8231.c113
1 files changed, 65 insertions, 48 deletions
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);
}
}