Annotation of sys/arch/i386/pci/via8231.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: via8231.c,v 1.7 2006/09/19 11:06:34 jsg Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1999 The NetBSD Foundation, Inc.
! 5: * All rights reserved.
! 6: *
! 7: * This code is derived from software contributed to The NetBSD Foundation
! 8: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
! 9: * NASA Ames Research Center.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39: /*
! 40: * Copyright (c) 2005, by Michael Shalayeff
! 41: * Copyright (c) 2003, by Matthew Gream
! 42: * Copyright (c) 1999, by UCHIYAMA Yasushi
! 43: * All rights reserved.
! 44: *
! 45: * Redistribution and use in source and binary forms, with or without
! 46: * modification, are permitted provided that the following conditions
! 47: * are met:
! 48: * 1. Redistributions of source code must retain the above copyright
! 49: * notice, this list of conditions and the following disclaimer.
! 50: * 2. The name of the developer may NOT be used to endorse or promote products
! 51: * derived from this software without specific prior written permission.
! 52: *
! 53: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 54: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 55: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 56: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 57: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 58: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 59: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 60: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 61: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 62: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 63: * SUCH DAMAGE.
! 64: */
! 65:
! 66: /*
! 67: * Support for the VIA Technologies Inc. VIA8231 PCI to ISA Bridge
! 68: * Based upon documentation:
! 69: * 1. VIA VT8231 South Bridge, Revision 1.85 (March 11, 2002), pg 73
! 70: * 2. VIA VT8237R South Bridge, Revision 2.06 (December 15, 2004), pg 100
! 71: * Derived from amd756.c
! 72: */
! 73:
! 74: #include <sys/param.h>
! 75: #include <sys/systm.h>
! 76: #include <sys/device.h>
! 77: #include <sys/malloc.h>
! 78:
! 79: #include <machine/intr.h>
! 80: #include <machine/bus.h>
! 81:
! 82: #include <dev/pci/pcivar.h>
! 83: #include <dev/pci/pcireg.h>
! 84: #include <dev/pci/pcidevs.h>
! 85:
! 86: #include <i386/pci/pcibiosvar.h>
! 87: #include <i386/pci/via8231reg.h>
! 88:
! 89: struct via8231_handle {
! 90: bus_space_tag_t ph_iot;
! 91: bus_space_handle_t ph_regs_ioh;
! 92: pci_chipset_tag_t ph_pc;
! 93: pcitag_t ph_tag;
! 94: int flags;
! 95: #define VT8237 0x0001
! 96: };
! 97:
! 98: int via8231_getclink(pciintr_icu_handle_t, int, int *);
! 99: int via8231_get_intr(pciintr_icu_handle_t, int, int *);
! 100: int via8231_set_intr(pciintr_icu_handle_t, int, int);
! 101: int via8231_get_trigger(pciintr_icu_handle_t, int, int *);
! 102: int via8231_set_trigger(pciintr_icu_handle_t, int, int);
! 103: #ifdef VIA8231_DEBUG
! 104: static void via8231_pir_dump(const char*, struct via8231_handle *);
! 105: #endif
! 106:
! 107: const struct pciintr_icu via8231_pci_icu = {
! 108: via8231_getclink,
! 109: via8231_get_intr,
! 110: via8231_set_intr,
! 111: via8231_get_trigger,
! 112: via8231_set_trigger,
! 113: };
! 114:
! 115: struct mask_shft_pair {
! 116: int mask;
! 117: int shft;
! 118: };
! 119:
! 120: static const struct mask_shft_pair via8231_routing_cnfg[VIA8231_LINK_MAX+1] = {
! 121: { 0x0f, 0+4 }, /*PINTA#*/
! 122: { 0x0f, 8+0 }, /*PINTB#*/
! 123: { 0x0f, 8+4 }, /*PINTC#*/
! 124: { 0x0f, 16+4 } /*PINTD#*/
! 125: };
! 126:
! 127: #define VIA8231_GET_TRIGGER_CNFG(reg, pirq) \
! 128: ((reg) & (1 << (3 - (clink & 3))))
! 129: #define VIA8231_SET_TRIGGER_CNFG(reg, clink, cfg) \
! 130: (((reg) & ~(1 << (3 - (clink & 3)))) | ((cfg) << (3 - (clink & 3))))
! 131:
! 132: #define VIA8231_GET_ROUTING_CNFG(reg, pirq) \
! 133: (((reg) >> via8231_routing_cnfg[(pirq)].shft) & \
! 134: via8231_routing_cnfg[(pirq)].mask)
! 135:
! 136: #define VIA8231_SET_ROUTING_CNFG(reg, pirq, cfg) \
! 137: (((reg) & ~(via8231_routing_cnfg[(pirq)].mask << \
! 138: via8231_routing_cnfg[(pirq)].shft)) | \
! 139: (((cfg) & via8231_routing_cnfg[(pirq)].mask) << \
! 140: via8231_routing_cnfg[(pirq)].shft))
! 141:
! 142: int
! 143: via8231_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
! 144: pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
! 145: {
! 146: struct via8231_handle *ph;
! 147: pcireg_t id;
! 148:
! 149: ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
! 150: if (ph == NULL)
! 151: return (1);
! 152:
! 153: ph->ph_iot = iot;
! 154: ph->ph_pc = pc;
! 155: ph->ph_tag = tag;
! 156: id = pci_conf_read(pc, tag, PCI_ID_REG);
! 157: ph->flags = PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
! 158: PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT8231_ISA? 0 : VT8237;
! 159:
! 160: *ptagp = &via8231_pci_icu;
! 161: *phandp = ph;
! 162:
! 163: #ifdef VIA8231_DEBUG
! 164: via8231_pir_dump("via8231_init", ph);
! 165: #endif
! 166:
! 167: return 0;
! 168: }
! 169:
! 170: int
! 171: via8231_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
! 172: {
! 173: struct via8231_handle *ph = v;
! 174:
! 175: if ((ph->flags & VT8237) && !VIA8237_LINK_LEGAL(link - 1))
! 176: return (1);
! 177:
! 178: if (!(ph->flags & VT8237) && !VIA8231_LINK_LEGAL(link - 1))
! 179: return (1);
! 180:
! 181: *clinkp = link - 1;
! 182: return (0);
! 183: }
! 184:
! 185: int
! 186: via8231_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
! 187: {
! 188: struct via8231_handle *ph = v;
! 189: int reg, val;
! 190:
! 191: if (VIA8237_LINK_LEGAL(clink) == 0)
! 192: return (1);
! 193:
! 194: if (VIA8231_LINK_LEGAL(clink)) {
! 195: reg = VIA8231_GET_ROUTING(ph);
! 196: val = VIA8231_GET_ROUTING_CNFG(reg, clink);
! 197: } else {
! 198: reg = VIA8237_GET_ROUTING(ph);
! 199: val = (reg >> ((clink & 3) * 4)) & 0xf;
! 200: }
! 201:
! 202: *irqp = (val == VIA8231_ROUTING_CNFG_DISABLED) ?
! 203: I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
! 204:
! 205: return (0);
! 206: }
! 207:
! 208: int
! 209: via8231_set_intr(pciintr_icu_handle_t v, int clink, int irq)
! 210: {
! 211: struct via8231_handle *ph = v;
! 212: int reg;
! 213:
! 214: if (VIA8237_LINK_LEGAL(clink) == 0 || VIA8231_PIRQ_LEGAL(irq) == 0)
! 215: return (1);
! 216:
! 217: #ifdef VIA8231_DEBUG
! 218: printf("via8231_set_intr: link(%02x) --> irq(%02x)\n", clink, irq);
! 219: via8231_pir_dump("via8231_set_intr: ", ph);
! 220: #endif
! 221:
! 222: if (VIA8231_LINK_LEGAL(clink)) {
! 223: reg = VIA8231_GET_ROUTING(ph);
! 224: VIA8231_SET_ROUTING(ph,
! 225: VIA8231_SET_ROUTING_CNFG(reg, clink, irq));
! 226: } else {
! 227: reg = VIA8237_GET_ROUTING(ph);
! 228: VIA8237_SET_ROUTING(ph, (reg & ~(0xf << (clink & 3))) |
! 229: ((irq & 0xf) << (clink & 3)));
! 230: }
! 231:
! 232: return (0);
! 233: }
! 234:
! 235: int
! 236: via8231_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
! 237: {
! 238: struct via8231_handle *ph = v;
! 239: int reg, clink, max, pciirq;
! 240:
! 241: if (VIA8231_PIRQ_LEGAL(irq) == 0)
! 242: return (1);
! 243:
! 244: max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
! 245: for (clink = 0; clink <= max; clink++) {
! 246: via8231_get_intr(v, clink, &pciirq);
! 247: if (pciirq == irq) {
! 248: reg = VIA8231_LINK_LEGAL(clink)?
! 249: VIA8231_GET_TRIGGER(ph):
! 250: VIA8237_GET_TRIGGER(ph);
! 251: *triggerp = VIA8231_GET_TRIGGER_CNFG(reg, clink)?
! 252: IST_EDGE : IST_LEVEL;
! 253: return (0);
! 254: }
! 255: }
! 256:
! 257: return (1);
! 258: }
! 259:
! 260: int
! 261: via8231_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
! 262: {
! 263: struct via8231_handle *ph = v;
! 264: int reg, clink, max, pciirq;
! 265:
! 266: if (VIA8231_PIRQ_LEGAL(irq) == 0 || VIA8231_TRIG_LEGAL(trigger) == 0)
! 267: return (1);
! 268:
! 269: #ifdef VIA8231_DEBUG
! 270: printf("via8231_set_trig: irq(%02x) --> trig(%02x)\n", irq, trigger);
! 271: via8231_pir_dump("via8231_set_trig: ", ph);
! 272: #endif
! 273:
! 274: max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
! 275: for (clink = 0; clink <= VIA8231_LINK_MAX; clink++) {
! 276: via8231_get_intr(v, clink, &pciirq);
! 277: if (pciirq == irq) {
! 278: reg = VIA8231_LINK_LEGAL(clink)?
! 279: VIA8231_GET_TRIGGER(ph):
! 280: VIA8237_GET_TRIGGER(ph);
! 281: switch (trigger) {
! 282: case IST_LEVEL:
! 283: reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
! 284: VIA8231_TRIGGER_CNFG_LEVEL);
! 285: break;
! 286: case IST_EDGE:
! 287: reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
! 288: VIA8231_TRIGGER_CNFG_EDGE);
! 289: break;
! 290: default:
! 291: return (1);
! 292: }
! 293: if (VIA8231_LINK_LEGAL(clink))
! 294: VIA8231_SET_TRIGGER(ph, reg);
! 295: else
! 296: VIA8237_SET_TRIGGER(ph, reg);
! 297: return (0);
! 298: }
! 299: }
! 300:
! 301: return (1);
! 302: }
! 303:
! 304: #ifdef VIA8231_DEBUG
! 305: static void
! 306: via8231_pir_dump(const char *m, struct via8231_handle *ph)
! 307: {
! 308: int a, b;
! 309:
! 310: a = VIA8231_GET_TRIGGER(ph);
! 311: b = VIA8231_GET_ROUTING(ph);
! 312:
! 313: printf("%s STATE: trigger(%02x), routing(%08x)\n", m, a, b);
! 314: }
! 315: #endif
CVSweb