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