Annotation of sys/arch/i386/pci/opti82c700.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: opti82c700.c,v 1.7 2006/09/19 11:06:34 jsg Exp $ */
! 2: /* $NetBSD: opti82c700.c,v 1.2 2000/07/18 11:07:20 soda Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1999 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
! 10: * NASA Ames Research Center.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the NetBSD
! 23: * Foundation, Inc. and its contributors.
! 24: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 25: * contributors may be used to endorse or promote products derived
! 26: * from this software without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 38: * POSSIBILITY OF SUCH DAMAGE.
! 39: */
! 40:
! 41: /*
! 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 Opti 82c700 FireStar PCI-ISA bridge interrupt controller.
! 68: */
! 69:
! 70: #include <sys/param.h>
! 71: #include <sys/systm.h>
! 72: #include <sys/device.h>
! 73: #include <sys/malloc.h>
! 74:
! 75: #include <machine/intr.h>
! 76: #include <machine/bus.h>
! 77:
! 78: #include <dev/pci/pcivar.h>
! 79: #include <dev/pci/pcireg.h>
! 80: #include <dev/pci/pcidevs.h>
! 81:
! 82: #include <i386/pci/pcibiosvar.h>
! 83: #include <i386/pci/opti82c700reg.h>
! 84:
! 85: #ifdef FIRESTARDEBUG
! 86: #define DPRINTF(arg) printf arg
! 87: #else
! 88: #define DPRINTF(arg)
! 89: #endif
! 90:
! 91: int opti82c700_getclink(pciintr_icu_handle_t, int, int *);
! 92: int opti82c700_get_intr(pciintr_icu_handle_t, int, int *);
! 93: int opti82c700_set_intr(pciintr_icu_handle_t, int, int);
! 94: int opti82c700_get_trigger(pciintr_icu_handle_t, int, int *);
! 95: int opti82c700_set_trigger(pciintr_icu_handle_t, int, int);
! 96:
! 97: const struct pciintr_icu opti82c700_pci_icu = {
! 98: opti82c700_getclink,
! 99: opti82c700_get_intr,
! 100: opti82c700_set_intr,
! 101: opti82c700_get_trigger,
! 102: opti82c700_set_trigger,
! 103: };
! 104:
! 105: struct opti82c700_handle {
! 106: pci_chipset_tag_t ph_pc;
! 107: pcitag_t ph_tag;
! 108: };
! 109:
! 110: int opti82c700_addr(int, int *, int *);
! 111: #ifdef FIRESTARDEBUG
! 112: void opti82c700_pir_dump(struct opti82c700_handle *);
! 113: #endif
! 114:
! 115: int
! 116: opti82c700_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
! 117: pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
! 118: {
! 119: struct opti82c700_handle *ph;
! 120:
! 121: ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
! 122: if (ph == NULL)
! 123: return (1);
! 124:
! 125: ph->ph_pc = pc;
! 126: ph->ph_tag = tag;
! 127: #ifdef FIRESTARDEBUG
! 128: opti82c700_pir_dump(ph);
! 129: #endif
! 130: *ptagp = &opti82c700_pci_icu;
! 131: *phandp = ph;
! 132: return (0);
! 133: }
! 134:
! 135: int
! 136: opti82c700_addr(int link, int *addrofs, int *ofs)
! 137: {
! 138: int regofs, src;
! 139:
! 140: regofs = FIRESTAR_PIR_REGOFS(link);
! 141: src = FIRESTAR_PIR_SELECTSRC(link);
! 142:
! 143: switch (src) {
! 144: case FIRESTAR_PIR_SELECT_NONE:
! 145: return (1);
! 146:
! 147: case FIRESTAR_PIR_SELECT_IRQ:
! 148: if (regofs < 0 || regofs > 7)
! 149: return (1);
! 150: *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2);
! 151: *ofs = (regofs & 3) << 3;
! 152: break;
! 153:
! 154: case FIRESTAR_PIR_SELECT_PIRQ:
! 155: /* FALLTHROUGH */
! 156: case FIRESTAR_PIR_SELECT_BRIDGE:
! 157: if (regofs < 0 || regofs > 3)
! 158: return (1);
! 159: *addrofs = FIRESTAR_CFG_INTR_PIRQ;
! 160: *ofs = regofs << 2;
! 161: break;
! 162:
! 163: default:
! 164: return (1);
! 165: }
! 166:
! 167: return (0);
! 168: }
! 169:
! 170: int
! 171: opti82c700_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
! 172: {
! 173: DPRINTF(("FireStar link value 0x%x: ", link));
! 174:
! 175: switch (FIRESTAR_PIR_SELECTSRC(link)) {
! 176: default:
! 177: DPRINTF(("bogus IRQ selection source\n"));
! 178: return (1);
! 179: case FIRESTAR_PIR_SELECT_NONE:
! 180: DPRINTF(("No interrupt connection\n"));
! 181: return (1);
! 182: case FIRESTAR_PIR_SELECT_IRQ:
! 183: DPRINTF(("FireStar IRQ pin"));
! 184: break;
! 185: case FIRESTAR_PIR_SELECT_PIRQ:
! 186: DPRINTF(("FireStar PIO pin or Serial IRQ PIRQ#"));
! 187: break;
! 188: case FIRESTAR_PIR_SELECT_BRIDGE:
! 189: DPRINTF(("FireBridge 1 INTx# pin"));
! 190: break;
! 191: }
! 192:
! 193: DPRINTF((" REGOFST:%#x\n", FIRESTAR_PIR_REGOFS(link)));
! 194: *clinkp = link;
! 195:
! 196: return (0);
! 197: }
! 198:
! 199: int
! 200: opti82c700_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
! 201: {
! 202: struct opti82c700_handle *ph = v;
! 203: pcireg_t reg;
! 204: int val, addrofs, ofs;
! 205:
! 206: if (opti82c700_addr(clink, &addrofs, &ofs))
! 207: return (1);
! 208:
! 209: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 210: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
! 211:
! 212: *irqp = (val == FIRESTAR_PIRQ_NONE) ?
! 213: I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
! 214:
! 215: return (0);
! 216: }
! 217:
! 218: int
! 219: opti82c700_set_intr(pciintr_icu_handle_t v, int clink, int irq)
! 220: {
! 221: struct opti82c700_handle *ph = v;
! 222: int addrofs, ofs;
! 223: pcireg_t reg;
! 224:
! 225: if (FIRESTAR_LEGAL_IRQ(irq) == 0)
! 226: return (1);
! 227:
! 228: if (opti82c700_addr(clink, &addrofs, &ofs))
! 229: return (1);
! 230:
! 231: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 232: reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs);
! 233: reg |= (irq << ofs);
! 234: pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
! 235:
! 236: return (0);
! 237: }
! 238:
! 239: int
! 240: opti82c700_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
! 241: {
! 242: struct opti82c700_handle *ph = v;
! 243: int i, val, addrofs, ofs;
! 244: pcireg_t reg;
! 245:
! 246: if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
! 247: /* ISA IRQ? */
! 248: *triggerp = IST_EDGE;
! 249: return (0);
! 250: }
! 251:
! 252: /*
! 253: * Search PCIDV1 registers.
! 254: */
! 255: for (i = 0; i < 8; i++) {
! 256: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
! 257: i), &addrofs, &ofs);
! 258: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 259: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
! 260: if (val != irq)
! 261: continue;
! 262: val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) &
! 263: FIRESTAR_TRIGGER_MASK;
! 264: *triggerp = val ? IST_LEVEL : IST_EDGE;
! 265: return (0);
! 266: }
! 267:
! 268: /*
! 269: * Search PIO PCIIRQ.
! 270: */
! 271: for (i = 0; i < 4; i++) {
! 272: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
! 273: i), &addrofs, &ofs);
! 274: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 275: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
! 276: if (val != irq)
! 277: continue;
! 278: *triggerp = IST_LEVEL;
! 279: return (0);
! 280: }
! 281:
! 282: return (1);
! 283: }
! 284:
! 285: int
! 286: opti82c700_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
! 287: {
! 288: struct opti82c700_handle *ph = v;
! 289: int i, val, addrofs, ofs;
! 290: pcireg_t reg;
! 291:
! 292: if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
! 293: /* ISA IRQ? */
! 294: return ((trigger != IST_LEVEL) ? 0 : 1);
! 295: }
! 296:
! 297: /*
! 298: * Search PCIDV1 registers.
! 299: */
! 300: for (i = 0; i < 8; i++) {
! 301: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
! 302: i), &addrofs, &ofs);
! 303: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 304: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
! 305: if (val != irq)
! 306: continue;
! 307: if (trigger == IST_LEVEL)
! 308: reg |= (FIRESTAR_TRIGGER_MASK <<
! 309: (FIRESTAR_TRIGGER_SHIFT + ofs));
! 310: else
! 311: reg &= ~(FIRESTAR_TRIGGER_MASK <<
! 312: (FIRESTAR_TRIGGER_SHIFT + ofs));
! 313: pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
! 314: return (0);
! 315: }
! 316:
! 317: /*
! 318: * Search PIO PCIIRQ.
! 319: */
! 320: for (i = 0; i < 4; i++) {
! 321: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
! 322: i), &addrofs, &ofs);
! 323: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
! 324: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
! 325: if (val != irq)
! 326: continue;
! 327: return (trigger == IST_LEVEL ? 0 : 1);
! 328: }
! 329:
! 330: return (1);
! 331: }
CVSweb