1 /* $OpenBSD: siop_pci_common.c,v 1.19 2014/12/19 22:44:58 guenther Exp $ */ 2 /* $NetBSD: siop_pci_common.c,v 1.25 2005/06/28 00:28:42 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 2000 Manuel Bouyer. 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* SYM53c8xx PCI-SCSI I/O Processors driver: PCI front-end */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/device.h> 33 #include <sys/malloc.h> 34 #include <sys/buf.h> 35 #include <sys/kernel.h> 36 #include <sys/endian.h> 37 38 #include <dev/pci/pcireg.h> 39 #include <dev/pci/pcivar.h> 40 #include <dev/pci/pcidevs.h> 41 42 #include <scsi/scsi_all.h> 43 #include <scsi/scsiconf.h> 44 45 #include <dev/ic/siopreg.h> 46 #include <dev/ic/siopvar_common.h> 47 #include <dev/pci/siop_pci_common.h> 48 49 /* List (array, really :) of chips we know how to handle */ 50 const struct siop_product_desc siop_products[] = { 51 { PCI_PRODUCT_SYMBIOS_810, 52 0x00, 53 SF_PCI_RL | SF_CHIP_LS, 54 4, 8, 3, 250, 0 55 }, 56 { PCI_PRODUCT_SYMBIOS_810, 57 0x10, 58 SF_PCI_RL | SF_PCI_BOF | SF_CHIP_PF | SF_CHIP_LS, 59 4, 8, 3, 250, 0 60 }, 61 { PCI_PRODUCT_SYMBIOS_815, 62 0x00, 63 SF_PCI_RL | SF_PCI_BOF, 64 4, 8, 3, 250, 0 65 }, 66 { PCI_PRODUCT_SYMBIOS_820, 67 0x00, 68 SF_PCI_RL | SF_CHIP_LS | SF_BUS_WIDE, 69 4, 8, 3, 250, 0 70 }, 71 { PCI_PRODUCT_SYMBIOS_825, 72 0x00, 73 SF_PCI_RL | SF_PCI_BOF | SF_BUS_WIDE, 74 4, 8, 3, 250, 0 75 }, 76 { PCI_PRODUCT_SYMBIOS_825, 77 0x10, 78 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 79 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS | 80 SF_BUS_WIDE, 81 7, 8, 3, 250, 4096 82 }, 83 { PCI_PRODUCT_SYMBIOS_860, 84 0x00, 85 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 86 SF_CHIP_PF | SF_CHIP_LS | 87 SF_BUS_ULTRA, 88 4, 8, 5, 125, 0 89 }, 90 { PCI_PRODUCT_SYMBIOS_875, 91 0x00, 92 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 93 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS | 94 SF_BUS_ULTRA | SF_BUS_WIDE, 95 7, 16, 5, 125, 4096 96 }, 97 { PCI_PRODUCT_SYMBIOS_875, 98 0x02, 99 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 100 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | 101 SF_CHIP_LS | SF_CHIP_10REGS | 102 SF_BUS_ULTRA | SF_BUS_WIDE, 103 7, 16, 5, 125, 4096 104 }, 105 { PCI_PRODUCT_SYMBIOS_875J, 106 0x00, 107 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 108 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | 109 SF_CHIP_LS | SF_CHIP_10REGS | 110 SF_BUS_ULTRA | SF_BUS_WIDE, 111 7, 16, 5, 125, 4096 112 }, 113 { PCI_PRODUCT_SYMBIOS_885, 114 0x00, 115 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 116 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | 117 SF_CHIP_LS | SF_CHIP_10REGS | 118 SF_BUS_ULTRA | SF_BUS_WIDE, 119 7, 16, 5, 125, 4096 120 }, 121 { PCI_PRODUCT_SYMBIOS_895, 122 0x00, 123 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 124 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | 125 SF_CHIP_LS | SF_CHIP_10REGS | 126 SF_BUS_ULTRA2 | SF_BUS_WIDE, 127 7, 31, 7, 62, 4096 128 }, 129 { PCI_PRODUCT_SYMBIOS_896, 130 0x00, 131 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 132 SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | 133 SF_CHIP_LS | SF_CHIP_10REGS | 134 SF_BUS_ULTRA2 | SF_BUS_WIDE, 135 7, 31, 7, 62, 8192 136 }, 137 { PCI_PRODUCT_SYMBIOS_895A, 138 0x00, 139 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 140 SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | 141 SF_CHIP_LS | SF_CHIP_10REGS | 142 SF_BUS_ULTRA2 | SF_BUS_WIDE, 143 7, 31, 7, 62, 8192 144 }, 145 { PCI_PRODUCT_SYMBIOS_1010, 146 0x00, 147 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 148 SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | 149 SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | 150 SF_CHIP_GEBUG | 151 SF_BUS_ULTRA3 | SF_BUS_WIDE, 152 7, 31, 0, 62, 8192 153 }, 154 { PCI_PRODUCT_SYMBIOS_1010, 155 0x01, 156 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 157 SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | 158 SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | SF_CHIP_DT | 159 SF_CHIP_GEBUG | 160 SF_BUS_ULTRA3 | SF_BUS_WIDE, 161 7, 62, 0, 62, 8192 162 }, 163 { PCI_PRODUCT_SYMBIOS_1010_2, 164 0x00, 165 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 166 SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | 167 SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | SF_CHIP_DT | 168 SF_CHIP_AAIP | 169 SF_BUS_ULTRA3 | SF_BUS_WIDE, 170 7, 62, 0, 62, 8192 171 }, 172 { PCI_PRODUCT_SYMBIOS_1510D, 173 0x00, 174 SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | 175 SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | 176 SF_CHIP_LS | SF_CHIP_10REGS | 177 SF_BUS_ULTRA2 | SF_BUS_WIDE, 178 7, 31, 7, 62, 4096 179 }, 180 { 0, 181 0x00, 182 0x00, 183 0, 0, 0, 0, 0 184 }, 185 }; 186 187 const struct siop_product_desc * 188 siop_lookup_product(u_int32_t id, int rev) 189 { 190 const struct siop_product_desc *pp; 191 const struct siop_product_desc *rp = NULL; 192 193 if (PCI_VENDOR(id) != PCI_VENDOR_SYMBIOS) 194 return NULL; 195 196 for (pp = siop_products; pp->product != 0; pp++) { 197 if (PCI_PRODUCT(id) == pp->product && pp->revision <= rev) 198 if (rp == NULL || pp->revision > rp->revision) 199 rp = pp; 200 } 201 return rp; 202 } 203 204 int 205 siop_pci_attach_common(struct siop_pci_common_softc *pci_sc, 206 struct siop_common_softc *siop_sc, struct pci_attach_args *pa, 207 int (*intr)(void*)) 208 { 209 pci_chipset_tag_t pc = pa->pa_pc; 210 pcitag_t tag = pa->pa_tag; 211 const char *intrstr; 212 pci_intr_handle_t intrhandle; 213 bus_space_tag_t iot, memt; 214 bus_space_handle_t ioh, memh; 215 pcireg_t memtype; 216 int memh_valid, ioh_valid; 217 bus_addr_t ioaddr, memaddr; 218 bus_size_t iosize, memsize, ramsize; 219 220 pci_sc->sc_pp = 221 siop_lookup_product(pa->pa_id, PCI_REVISION(pa->pa_class)); 222 if (pci_sc->sc_pp == NULL) { 223 printf(": broken match/attach!\n"); 224 return 0; 225 } 226 /* copy interesting infos about the chip */ 227 siop_sc->features = pci_sc->sc_pp->features; 228 #ifdef SIOP_SYMLED /* XXX Should be a devprop! */ 229 siop_sc->features |= SF_CHIP_LED0; 230 #endif 231 siop_sc->maxburst = pci_sc->sc_pp->maxburst; 232 siop_sc->maxoff = pci_sc->sc_pp->maxoff; 233 siop_sc->clock_div = pci_sc->sc_pp->clock_div; 234 siop_sc->clock_period = pci_sc->sc_pp->clock_period; 235 siop_sc->ram_size = pci_sc->sc_pp->ram_size; 236 237 siop_sc->sc_reset = siop_pci_reset; 238 pci_sc->sc_pc = pc; 239 pci_sc->sc_tag = tag; 240 siop_sc->sc_dmat = pa->pa_dmat; 241 242 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x14); 243 switch (memtype) { 244 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: 245 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: 246 memh_valid = (pci_mapreg_map(pa, 0x14, memtype, 0, 247 &memt, &memh, &memaddr, &memsize, 0) == 0); 248 break; 249 default: 250 memh_valid = 0; 251 } 252 253 ioh_valid = (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, 254 &iot, &ioh, &ioaddr, &iosize, 0) == 0); 255 256 if (memh_valid) { 257 siop_sc->sc_rt = memt; 258 siop_sc->sc_rh = memh; 259 siop_sc->sc_raddr = memaddr; 260 } else if (ioh_valid) { 261 siop_sc->sc_rt = iot; 262 siop_sc->sc_rh = ioh; 263 siop_sc->sc_raddr = ioaddr; 264 } else { 265 printf(": unable to map device registers\n"); 266 return 0; 267 } 268 269 if (pci_intr_map(pa, &intrhandle) != 0) { 270 printf(": couldn't map interrupt\n"); 271 goto out; 272 } 273 intrstr = pci_intr_string(pa->pa_pc, intrhandle); 274 pci_sc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, 275 intr, siop_sc, siop_sc->sc_dev.dv_xname); 276 if (pci_sc->sc_ih != NULL) { 277 printf(": %s", 278 intrstr ? intrstr : "?"); 279 } else { 280 printf(": couldn't establish interrupt"); 281 if (intrstr != NULL) 282 printf(" at %s", intrstr); 283 printf("\n"); 284 goto out; 285 } 286 287 if (siop_sc->features & SF_CHIP_RAM) { 288 int bar; 289 switch (memtype) { 290 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: 291 bar = 0x18; 292 break; 293 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: 294 bar = 0x1c; 295 break; 296 default: 297 printf(": invalid memory type %d\n", memtype); 298 goto out; 299 } 300 if (pci_mapreg_map(pa, bar, memtype, 0, 301 &siop_sc->sc_ramt, &siop_sc->sc_ramh, 302 &siop_sc->sc_scriptaddr, &ramsize, 0) == 0) { 303 printf(", using %luK of on-board RAM", 304 (u_long)ramsize / 1024); 305 } else { 306 printf(", can't map on-board RAM"); 307 siop_sc->features &= ~SF_CHIP_RAM; 308 } 309 } 310 311 printf("\n"); 312 313 return (1); 314 315 out: 316 if (pci_sc->sc_ih) { 317 pci_intr_disestablish(pa->pa_pc, pci_sc->sc_ih); 318 pci_sc->sc_ih = NULL; 319 } 320 if (ioh_valid) 321 bus_space_unmap(iot, ioh, iosize); 322 if (memh_valid) 323 bus_space_unmap(memt, memh, memsize); 324 return (0); 325 } 326 327 void 328 siop_pci_reset(struct siop_common_softc *sc) 329 { 330 int dmode; 331 332 dmode = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE); 333 if (sc->features & SF_PCI_RL) 334 dmode |= DMODE_ERL; 335 if (sc->features & SF_PCI_RM) 336 dmode |= DMODE_ERMP; 337 if (sc->features & SF_PCI_BOF) 338 dmode |= DMODE_BOF; 339 if (sc->features & SF_PCI_CLS) 340 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, 341 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) | 342 DCNTL_CLSE); 343 if (sc->features & SF_PCI_WRI) 344 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3, 345 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) | 346 CTEST3_WRIE); 347 if (sc->maxburst) { 348 int ctest5 = bus_space_read_1(sc->sc_rt, sc->sc_rh, 349 SIOP_CTEST5); 350 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, 351 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) & 352 ~CTEST4_BDIS); 353 dmode &= ~DMODE_BL_MASK; 354 dmode |= ((sc->maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK; 355 ctest5 &= ~CTEST5_BBCK; 356 ctest5 |= (sc->maxburst - 1) & CTEST5_BBCK; 357 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5, ctest5); 358 } else { 359 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, 360 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) | 361 CTEST4_BDIS); 362 } 363 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE, dmode); 364 } 365