1 /* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 JF Hay. All rights reserved. 5 * Copyright (c) 2000 M. Warner Losh. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1996, 1998, 1999 31 * Christopher G. Demetriou. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by Christopher G. Demetriou 44 * for the NetBSD Project. 45 * 4. The name of the author may not be used to endorse or promote products 46 * derived from this software without specific prior written permission 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 50 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 51 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 52 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 57 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60 #include <sys/cdefs.h> 61 __FBSDID("$FreeBSD$"); 62 63 #include "opt_puc.h" 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/kernel.h> 68 #include <sys/module.h> 69 #include <sys/bus.h> 70 #include <sys/conf.h> 71 #include <sys/malloc.h> 72 73 #include <machine/bus.h> 74 #include <machine/resource.h> 75 #include <sys/rman.h> 76 77 #include <dev/pci/pcireg.h> 78 #include <dev/pci/pcivar.h> 79 80 #define PUC_ENTRAILS 1 81 #include <dev/puc/pucvar.h> 82 83 extern const struct puc_device_description puc_devices[]; 84 85 int puc_config_win877(struct puc_softc *); 86 87 static const struct puc_device_description * 88 puc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 89 uint32_t sprod) 90 { 91 int i; 92 93 #define checkreg(val, index) \ 94 (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 95 96 for (i = 0; puc_devices[i].name != NULL; i++) { 97 if (checkreg(vend, PUC_REG_VEND) && 98 checkreg(prod, PUC_REG_PROD) && 99 checkreg(svend, PUC_REG_SVEND) && 100 checkreg(sprod, PUC_REG_SPROD)) 101 return (&puc_devices[i]); 102 } 103 104 #undef checkreg 105 106 return (NULL); 107 } 108 109 static int 110 puc_pci_probe(device_t dev) 111 { 112 uint32_t v1, v2, d1, d2; 113 const struct puc_device_description *desc; 114 115 if ((pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) != 0) 116 return (ENXIO); 117 118 v1 = pci_read_config(dev, PCIR_VENDOR, 2); 119 d1 = pci_read_config(dev, PCIR_DEVICE, 2); 120 v2 = pci_read_config(dev, PCIR_SUBVEND_0, 2); 121 d2 = pci_read_config(dev, PCIR_SUBDEV_0, 2); 122 123 desc = puc_find_description(v1, d1, v2, d2); 124 if (desc == NULL) 125 return (ENXIO); 126 device_set_desc(dev, desc->name); 127 return (BUS_PROBE_DEFAULT); 128 } 129 130 static int 131 puc_pci_attach(device_t dev) 132 { 133 uint32_t v1, v2, d1, d2; 134 135 v1 = pci_read_config(dev, PCIR_VENDOR, 2); 136 d1 = pci_read_config(dev, PCIR_DEVICE, 2); 137 v2 = pci_read_config(dev, PCIR_SUBVEND_0, 2); 138 d2 = pci_read_config(dev, PCIR_SUBDEV_0, 2); 139 return (puc_attach(dev, puc_find_description(v1, d1, v2, d2))); 140 } 141 142 static device_method_t puc_pci_methods[] = { 143 /* Device interface */ 144 DEVMETHOD(device_probe, puc_pci_probe), 145 DEVMETHOD(device_attach, puc_pci_attach), 146 147 DEVMETHOD(bus_alloc_resource, puc_alloc_resource), 148 DEVMETHOD(bus_release_resource, puc_release_resource), 149 DEVMETHOD(bus_get_resource, puc_get_resource), 150 DEVMETHOD(bus_read_ivar, puc_read_ivar), 151 DEVMETHOD(bus_setup_intr, puc_setup_intr), 152 DEVMETHOD(bus_teardown_intr, puc_teardown_intr), 153 DEVMETHOD(bus_print_child, bus_generic_print_child), 154 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 155 { 0, 0 } 156 }; 157 158 static driver_t puc_pci_driver = { 159 "puc", 160 puc_pci_methods, 161 sizeof(struct puc_softc), 162 }; 163 164 DRIVER_MODULE(puc, pci, puc_pci_driver, puc_devclass, 0, 0); 165 DRIVER_MODULE(puc, cardbus, puc_pci_driver, puc_devclass, 0, 0); 166 167 168 #define rdspio(indx) (bus_space_write_1(bst, bsh, efir, indx), \ 169 bus_space_read_1(bst, bsh, efdr)) 170 #define wrspio(indx,data) (bus_space_write_1(bst, bsh, efir, indx), \ 171 bus_space_write_1(bst, bsh, efdr, data)) 172 173 #ifdef PUC_DEBUG 174 static void 175 puc_print_win877(bus_space_tag_t bst, bus_space_handle_t bsh, u_int efir, 176 u_int efdr) 177 { 178 u_char cr00, cr01, cr04, cr09, cr0d, cr14, cr15, cr16, cr17; 179 u_char cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32; 180 181 cr00 = rdspio(0x00); 182 cr01 = rdspio(0x01); 183 cr04 = rdspio(0x04); 184 cr09 = rdspio(0x09); 185 cr0d = rdspio(0x0d); 186 cr14 = rdspio(0x14); 187 cr15 = rdspio(0x15); 188 cr16 = rdspio(0x16); 189 cr17 = rdspio(0x17); 190 cr18 = rdspio(0x18); 191 cr19 = rdspio(0x19); 192 cr24 = rdspio(0x24); 193 cr25 = rdspio(0x25); 194 cr28 = rdspio(0x28); 195 cr2c = rdspio(0x2c); 196 cr31 = rdspio(0x31); 197 cr32 = rdspio(0x32); 198 printf("877T: cr00 %x, cr01 %x, cr04 %x, cr09 %x, cr0d %x, cr14 %x, " 199 "cr15 %x, cr16 %x, cr17 %x, cr18 %x, cr19 %x, cr24 %x, cr25 %x, " 200 "cr28 %x, cr2c %x, cr31 %x, cr32 %x\n", cr00, cr01, cr04, cr09, 201 cr0d, cr14, cr15, cr16, cr17, 202 cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32); 203 } 204 #endif 205 206 int 207 puc_config_win877(struct puc_softc *sc) 208 { 209 u_char val; 210 u_int efir, efdr; 211 bus_space_tag_t bst; 212 bus_space_handle_t bsh; 213 struct resource *res; 214 215 res = sc->sc_bar_mappings[0].res; 216 217 bst = rman_get_bustag(res); 218 bsh = rman_get_bushandle(res); 219 220 /* configure the first W83877TF */ 221 bus_space_write_1(bst, bsh, 0x250, 0x89); 222 efir = 0x251; 223 efdr = 0x252; 224 val = rdspio(0x09) & 0x0f; 225 if (val != 0x0c) { 226 printf("conf_win877: Oops not a W83877TF\n"); 227 return (ENXIO); 228 } 229 230 #ifdef PUC_DEBUG 231 printf("before: "); 232 puc_print_win877(bst, bsh, efir, efdr); 233 #endif 234 235 val = rdspio(0x16); 236 val |= 0x04; 237 wrspio(0x16, val); 238 val &= ~0x04; 239 wrspio(0x16, val); 240 241 wrspio(0x24, 0x2e8 >> 2); 242 wrspio(0x25, 0x2f8 >> 2); 243 wrspio(0x17, 0x03); 244 wrspio(0x28, 0x43); 245 246 #ifdef PUC_DEBUG 247 printf("after: "); 248 puc_print_win877(bst, bsh, efir, efdr); 249 #endif 250 251 bus_space_write_1(bst, bsh, 0x250, 0xaa); 252 253 /* configure the second W83877TF */ 254 bus_space_write_1(bst, bsh, 0x3f0, 0x87); 255 bus_space_write_1(bst, bsh, 0x3f0, 0x87); 256 efir = 0x3f0; 257 efdr = 0x3f1; 258 val = rdspio(0x09) & 0x0f; 259 if (val != 0x0c) { 260 printf("conf_win877: Oops not a W83877TF\n"); 261 return(ENXIO); 262 } 263 264 #ifdef PUC_DEBUG 265 printf("before: "); 266 puc_print_win877(bst, bsh, efir, efdr); 267 #endif 268 269 val = rdspio(0x16); 270 val |= 0x04; 271 wrspio(0x16, val); 272 val &= ~0x04; 273 wrspio(0x16, val); 274 275 wrspio(0x24, 0x3e8 >> 2); 276 wrspio(0x25, 0x3f8 >> 2); 277 wrspio(0x17, 0x03); 278 wrspio(0x28, 0x43); 279 280 #ifdef PUC_DEBUG 281 printf("after: "); 282 puc_print_win877(bst, bsh, efir, efdr); 283 #endif 284 285 bus_space_write_1(bst, bsh, 0x3f0, 0xaa); 286 return (0); 287 } 288 289 #undef rdspio 290 #undef wrspio 291 292