1 /* $OpenBSD: amd756.c,v 1.2 2001/01/25 00:07:40 mickey Exp $ */ 2 /* $NetBSD$ */ 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 Advanced Micro Devices AMD756 Peripheral Bus 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/amd756reg.h> 84 85 struct viper_handle { 86 bus_space_tag_t ph_iot; 87 bus_space_handle_t ph_regs_ioh; 88 pci_chipset_tag_t ph_pc; 89 pcitag_t ph_tag; 90 }; 91 92 int amd756_getclink __P((pciintr_icu_handle_t, int, int *)); 93 int amd756_get_intr __P((pciintr_icu_handle_t, int, int *)); 94 int amd756_set_intr __P((pciintr_icu_handle_t, int, int)); 95 int amd756_get_trigger __P((pciintr_icu_handle_t, int, int *)); 96 int amd756_set_trigger __P((pciintr_icu_handle_t, int, int)); 97 #ifdef VIPER_DEBUG 98 static void amd756_pir_dump __P((struct viper_handle *)); 99 #endif 100 101 const struct pciintr_icu amd756_pci_icu = { 102 amd756_getclink, 103 amd756_get_intr, 104 amd756_set_intr, 105 amd756_get_trigger, 106 amd756_set_trigger, 107 }; 108 109 110 int 111 amd756_init(pc, iot, tag, ptagp, phandp) 112 pci_chipset_tag_t pc; 113 bus_space_tag_t iot; 114 pcitag_t tag; 115 pciintr_icu_tag_t *ptagp; 116 pciintr_icu_handle_t *phandp; 117 { 118 struct viper_handle *ph; 119 120 ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT); 121 if (ph == NULL) 122 return (1); 123 124 ph->ph_iot = iot; 125 ph->ph_pc = pc; 126 ph->ph_tag = tag; 127 128 *ptagp = &amd756_pci_icu; 129 *phandp = ph; 130 131 #ifdef VIPER_DEBUG 132 amd756_pir_dump(ph); 133 #endif 134 135 return 0; 136 } 137 138 int 139 amd756_getclink(v, link, clinkp) 140 pciintr_icu_handle_t v; 141 int link, *clinkp; 142 { 143 if (AMD756_LEGAL_LINK(link - 1) == 0) 144 return (1); 145 146 *clinkp = link - 1; 147 return (0); 148 } 149 150 int 151 amd756_get_intr(v, clink, irqp) 152 pciintr_icu_handle_t v; 153 int clink, *irqp; 154 { 155 struct viper_handle *ph = v; 156 pcireg_t reg; 157 int val; 158 159 if (AMD756_LEGAL_LINK(clink) == 0) 160 return (1); 161 162 reg = AMD756_GET_PIIRQSEL(ph); 163 val = (reg >> (4*clink)) & 0x0f; 164 *irqp = (val == 0) ? 165 I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val; 166 167 return (0); 168 } 169 170 int 171 amd756_set_intr(v, clink, irq) 172 pciintr_icu_handle_t v; 173 int clink, irq; 174 { 175 struct viper_handle *ph = v; 176 int val; 177 pcireg_t reg; 178 179 if (AMD756_LEGAL_LINK(clink) == 0 || AMD756_LEGAL_IRQ(irq) == 0) 180 return (1); 181 182 reg = AMD756_GET_PIIRQSEL(ph); 183 amd756_get_intr(v, clink, &val); 184 reg &= ~(0x000f << (4*clink)); 185 reg |= irq << (4*clink); 186 AMD756_SET_PIIRQSEL(ph, reg); 187 188 return 0; 189 } 190 191 int 192 amd756_get_trigger(v, irq, triggerp) 193 pciintr_icu_handle_t v; 194 int irq, *triggerp; 195 { 196 struct viper_handle *ph = v; 197 int i, pciirq; 198 pcireg_t reg; 199 200 if (AMD756_LEGAL_IRQ(irq) == 0) 201 return (1); 202 203 for (i = 0; i <= 3; i++) { 204 amd756_get_intr(v, i, &pciirq); 205 if (pciirq == irq) { 206 reg = AMD756_GET_EDGESEL(ph); 207 if (reg & (1 << i)) 208 *triggerp = IST_EDGE; 209 else 210 *triggerp = IST_LEVEL; 211 break; 212 } 213 } 214 215 return 0; 216 } 217 218 int 219 amd756_set_trigger(v, irq, trigger) 220 pciintr_icu_handle_t v; 221 int irq, trigger; 222 { 223 struct viper_handle *ph = v; 224 int i, pciirq; 225 pcireg_t reg; 226 227 if (AMD756_LEGAL_IRQ(irq) == 0) 228 return (1); 229 230 for (i = 0; i <= 3; i++) { 231 amd756_get_intr(v, i, &pciirq); 232 if (pciirq == irq) { 233 reg = AMD756_GET_PIIRQSEL(ph); 234 if (trigger == IST_LEVEL) 235 reg &= ~(1 << (4*i)); 236 else 237 reg |= 1 << (4*i); 238 AMD756_SET_PIIRQSEL(ph, reg); 239 break; 240 } 241 } 242 243 return (0); 244 } 245 246 #ifdef VIPER_DEBUG 247 static void 248 amd756_pir_dump(ph) 249 struct viper_handle *ph; 250 { 251 int a, b; 252 253 printf ("VIPER PCI INTERRUPT ROUTING REGISTERS:\n"); 254 255 a = AMD756_GET_EDGESEL(ph); 256 b = AMD756_GET_PIIRQSEL(ph); 257 258 printf ("TRIGGER: %02x, ROUTING: %04x\n", a, b); 259 } 260 #endif 261