1 /* $NetBSD: opti82c700.c,v 1.1 1999/11/17 01:21:20 thorpej 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 /* 41 * Copyright (c) 1999, by UCHIYAMA Yasushi 42 * All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. The name of the developer may NOT be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 /* 66 * Support for the Opti 82c700 PCI-ISA bridge interrupt controller. 67 */ 68 69 #include <sys/param.h> 70 #include <sys/systm.h> 71 #include <sys/device.h> 72 #include <sys/malloc.h> 73 74 #include <machine/intr.h> 75 #include <machine/bus.h> 76 77 #include <dev/pci/pcivar.h> 78 #include <dev/pci/pcireg.h> 79 #include <dev/pci/pcidevs.h> 80 81 #include <i386/pci/pci_intr_fixup.h> 82 #include <i386/pci/opti82c700reg.h> 83 84 int opti82c700_getclink __P((pciintr_icu_handle_t, int, int *)); 85 int opti82c700_get_intr __P((pciintr_icu_handle_t, int, int *)); 86 int opti82c700_set_intr __P((pciintr_icu_handle_t, int, int)); 87 int opti82c700_get_trigger __P((pciintr_icu_handle_t, int, int *)); 88 int opti82c700_set_trigger __P((pciintr_icu_handle_t, int, int)); 89 90 const struct pciintr_icu opti82c700_pci_icu = { 91 opti82c700_getclink, 92 opti82c700_get_intr, 93 opti82c700_set_intr, 94 opti82c700_get_trigger, 95 opti82c700_set_trigger, 96 }; 97 98 struct opti82c700_handle { 99 pci_chipset_tag_t ph_pc; 100 pcitag_t ph_tag; 101 }; 102 103 int opti82c700_addr __P((int, int *, int *)); 104 105 int 106 opti82c700_init(pc, iot, tag, ptagp, phandp) 107 pci_chipset_tag_t pc; 108 bus_space_tag_t iot; 109 pcitag_t tag; 110 pciintr_icu_tag_t *ptagp; 111 pciintr_icu_handle_t *phandp; 112 { 113 struct opti82c700_handle *ph; 114 115 ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT); 116 if (ph == NULL) 117 return (1); 118 119 ph->ph_pc = pc; 120 ph->ph_tag = tag; 121 122 *ptagp = &opti82c700_pci_icu; 123 *phandp = ph; 124 return (0); 125 } 126 127 int 128 opti82c700_addr(link, addrofs, ofs) 129 int link, *addrofs, *ofs; 130 { 131 int regofs, src; 132 133 regofs = FIRESTAR_PIR_REGOFS(link); 134 src = FIRESTAR_PIR_SELECTSRC(link); 135 136 switch (src) { 137 case FIRESTAR_PIR_SELECT_NONE: 138 return (1); 139 140 case FIRESTAR_PIR_SELECT_IRQ: 141 if (regofs < 0 || regofs > 7) 142 return (1); 143 *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2); 144 *ofs = (regofs & 3) << 3; 145 break; 146 147 case FIRESTAR_PIR_SELECT_PIRQ: 148 case FIRESTAR_PIR_SELECT_BRIDGE: 149 if (regofs < 0 || regofs > 3) 150 return (1); 151 *addrofs = FIRESTAR_CFG_INTR_PIRQ; 152 *ofs = regofs << 2; 153 break; 154 155 default: 156 return (1); 157 } 158 159 return (0); 160 } 161 162 int 163 opti82c700_getclink(v, link, clinkp) 164 pciintr_icu_handle_t v; 165 int link, *clinkp; 166 { 167 168 if (FIRESTAR_LEGAL_LINK(link)) { 169 *clinkp = link; 170 return (0); 171 } 172 173 return (1); 174 } 175 176 int 177 opti82c700_get_intr(v, clink, irqp) 178 pciintr_icu_handle_t v; 179 int clink, *irqp; 180 { 181 struct opti82c700_handle *ph = v; 182 pcireg_t reg; 183 int val, addrofs, ofs; 184 185 if (FIRESTAR_LEGAL_LINK(clink) == 0) 186 return (1); 187 188 if (opti82c700_addr(clink, &addrofs, &ofs)) 189 return (1); 190 191 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs); 192 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK; 193 *irqp = (val == FIRESTAR_PIRQ_NONE) ? 0xff : val; 194 195 return (0); 196 } 197 198 int 199 opti82c700_set_intr(v, clink, irq) 200 pciintr_icu_handle_t v; 201 int clink, irq; 202 { 203 struct opti82c700_handle *ph = v; 204 int addrofs, ofs; 205 pcireg_t reg; 206 207 if (FIRESTAR_LEGAL_LINK(clink) == 0 || FIRESTAR_LEGAL_IRQ(irq) == 0) 208 return (1); 209 210 if (opti82c700_addr(clink, &addrofs, &ofs)) 211 return (1); 212 213 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs); 214 reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs); 215 reg |= (irq << ofs); 216 pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg); 217 218 return (0); 219 } 220 221 int 222 opti82c700_get_trigger(v, irq, triggerp) 223 pciintr_icu_handle_t v; 224 int irq, *triggerp; 225 { 226 struct opti82c700_handle *ph = v; 227 int i, val, addrofs, ofs; 228 pcireg_t reg; 229 230 if (FIRESTAR_LEGAL_IRQ(irq) == 0) { 231 /* ISA IRQ? */ 232 *triggerp = IST_EDGE; 233 return (0); 234 } 235 236 /* 237 * Search PCIDV1 registers. 238 */ 239 for (i = 0; i < 8; i++) { 240 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ, 241 i), &addrofs, &ofs); 242 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs); 243 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK; 244 if (val != irq) 245 continue; 246 val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) & 247 FIRESTAR_TRIGGER_MASK; 248 *triggerp = val ? IST_LEVEL : IST_EDGE; 249 return (0); 250 } 251 252 return (1); 253 } 254 255 int 256 opti82c700_set_trigger(v, irq, trigger) 257 pciintr_icu_handle_t v; 258 int irq, trigger; 259 { 260 struct opti82c700_handle *ph = v; 261 int i, val, addrofs, ofs; 262 pcireg_t reg; 263 264 if (FIRESTAR_LEGAL_IRQ(irq) == 0) { 265 /* ISA IRQ? */ 266 return ((trigger != IST_LEVEL) ? 0 : 1); 267 } 268 269 /* 270 * Search PCIDV1 registers. 271 */ 272 for (i = 0; i < 8; i++) { 273 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ, 274 i), &addrofs, &ofs); 275 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs); 276 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK; 277 if (val != irq) 278 continue; 279 if (trigger == IST_LEVEL) 280 reg |= (FIRESTAR_TRIGGER_MASK << 281 (FIRESTAR_TRIGGER_SHIFT + ofs)); 282 else 283 reg &= ~(FIRESTAR_TRIGGER_MASK << 284 (FIRESTAR_TRIGGER_SHIFT + ofs)); 285 pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg); 286 return (0); 287 } 288 289 return (1); 290 } 291