1 /* $NetBSD: gio.c,v 1.29 2007/02/22 16:54:26 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Soren S. Jorvang 5 * 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the 18 * NetBSD Project. See http://www.NetBSD.org/ for 19 * information about NetBSD. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: gio.c,v 1.29 2007/02/22 16:54:26 thorpej Exp $"); 37 38 #include "opt_ddb.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 44 #define _SGIMIPS_BUS_DMA_PRIVATE 45 #include <machine/bus.h> 46 #include <machine/machtype.h> 47 #include <machine/sysconf.h> 48 49 #include <sgimips/gio/gioreg.h> 50 #include <sgimips/gio/giovar.h> 51 #include <sgimips/gio/giodevs_data.h> 52 53 #include "locators.h" 54 #include "newport.h" 55 #include "grtwo.h" 56 #include "light.h" 57 #include "imc.h" 58 #include "pic.h" 59 60 #if (NNEWPORT > 0) 61 #include <sgimips/gio/newportvar.h> 62 #endif 63 64 #if (NGRTWO > 0) 65 #include <sgimips/gio/grtwovar.h> 66 #endif 67 68 #if (NLIGHT > 0) 69 #include <sgimips/gio/lightvar.h> 70 #endif 71 72 #if (NIMC > 0) 73 extern int imc_gio64_arb_config(int, uint32_t); 74 #endif 75 76 #if (NPIC > 0) 77 extern int pic_gio32_arb_config(int, uint32_t); 78 #endif 79 80 81 struct gio_softc { 82 struct device sc_dev; 83 }; 84 85 static int gio_match(struct device *, struct cfdata *, void *); 86 static void gio_attach(struct device *, struct device *, void *); 87 static int gio_print(void *, const char *); 88 static int gio_search(struct device *, struct cfdata *, 89 const int *, void *); 90 static int gio_submatch(struct device *, struct cfdata *, 91 const int *, void *); 92 93 CFATTACH_DECL(gio, sizeof(struct gio_softc), 94 gio_match, gio_attach, NULL, NULL); 95 96 struct gio_probe { 97 uint32_t slot; 98 uint32_t base; 99 uint32_t mach_type; 100 uint32_t mach_subtype; 101 }; 102 103 /* 104 * Expansion Slot Base Addresses 105 * 106 * IP12, IP20 and IP24 have two GIO connectors: GIO_SLOT_EXP0 and 107 * GIO_SLOT_EXP1. 108 * 109 * On IP24 these slots exist on the graphics board or the IOPLUS 110 * "mezzanine" on Indy and Challenge S, respectively. The IOPLUS or 111 * graphics board connects to the mainboard via a single GIO64 connector. 112 * 113 * IP22 has either three or four physical connectors, but only two 114 * electrically distinct slots: GIO_SLOT_GFX and GIO_SLOT_EXP0. 115 * 116 * It should also be noted that DMA is (mostly) not supported in Challenge 117 * S's GIO_SLOT_EXP1. See gio(4) for the story. 118 */ 119 static const struct gio_probe slot_bases[] = { 120 { GIO_SLOT_GFX, 0x1f000000, MACH_SGI_IP22, MACH_SGI_IP22_FULLHOUSE }, 121 122 { GIO_SLOT_EXP0, 0x1f400000, MACH_SGI_IP12, -1 }, 123 { GIO_SLOT_EXP0, 0x1f400000, MACH_SGI_IP20, -1 }, 124 { GIO_SLOT_EXP0, 0x1f400000, MACH_SGI_IP22, -1 }, 125 126 { GIO_SLOT_EXP1, 0x1f600000, MACH_SGI_IP12, -1 }, 127 { GIO_SLOT_EXP1, 0x1f600000, MACH_SGI_IP20, -1 }, 128 { GIO_SLOT_EXP1, 0x1f600000, MACH_SGI_IP22, MACH_SGI_IP22_GUINNESS }, 129 130 { 0, 0, 0, 0 } 131 }; 132 133 /* 134 * Graphic Board Base Addresses 135 * 136 * Graphics boards are not treated like expansion slot cards. Their base 137 * addresses do not necessarily correspond to GIO slot addresses and they 138 * do not contain product identification words. 139 */ 140 static const struct gio_probe gfx_bases[] = { 141 /* grtwo, and newport on IP22 */ 142 { -1, 0x1f000000, MACH_SGI_IP12, -1 }, 143 { -1, 0x1f000000, MACH_SGI_IP20, -1 }, 144 { -1, 0x1f000000, MACH_SGI_IP22, -1 }, 145 146 /* light */ 147 { -1, 0x1f3f0000, MACH_SGI_IP12, -1 }, 148 { -1, 0x1f3f0000, MACH_SGI_IP20, -1 }, 149 150 /* light (dual headed) */ 151 { -1, 0x1f3f8000, MACH_SGI_IP12, -1 }, 152 { -1, 0x1f3f8000, MACH_SGI_IP20, -1 }, 153 154 /* grtwo, and newport on IP22 */ 155 { -1, 0x1f400000, MACH_SGI_IP12, -1 }, 156 { -1, 0x1f400000, MACH_SGI_IP20, -1 }, 157 { -1, 0x1f400000, MACH_SGI_IP22, -1 }, 158 159 /* grtwo */ 160 { -1, 0x1f600000, MACH_SGI_IP12, -1 }, 161 { -1, 0x1f600000, MACH_SGI_IP20, -1 }, 162 { -1, 0x1f600000, MACH_SGI_IP22, -1 }, 163 164 /* newport */ 165 { -1, 0x1f800000, MACH_SGI_IP22, MACH_SGI_IP22_FULLHOUSE }, 166 167 /* newport */ 168 { -1, 0x1fc00000, MACH_SGI_IP22, MACH_SGI_IP22_FULLHOUSE }, 169 170 { 0, 0, 0, 0 } 171 }; 172 173 /* maximum number of graphics boards possible (arbitrarily large estimate) */ 174 #define MAXGFX 8 175 176 static int 177 gio_match(struct device *parent, struct cfdata *match, void *aux) 178 { 179 180 return 1; 181 } 182 183 static void 184 gio_attach(struct device *parent, struct device *self, void *aux) 185 { 186 struct gio_attach_args ga; 187 uint32_t gfx[MAXGFX]; 188 int i, j, ngfx; 189 190 printf("\n"); 191 192 ngfx = 0; 193 memset(gfx, 0, sizeof(gfx)); 194 195 /* 196 * Attach graphics devices first. They do not contain a Product 197 * Identification Word and have no slot number. 198 * 199 * Record addresses to which graphics devices attach so that 200 * we do not confuse them with expansion slots, should the 201 * addresses coincide. 202 */ 203 for (i = 0; gfx_bases[i].base != 0; i++) { 204 /* skip slots that don't apply to us */ 205 if (gfx_bases[i].mach_type != mach_type) 206 continue; 207 208 if (gfx_bases[i].mach_subtype != -1 && 209 gfx_bases[i].mach_subtype != mach_subtype) 210 continue; 211 212 ga.ga_slot = -1; 213 ga.ga_addr = gfx_bases[i].base; 214 ga.ga_iot = SGIMIPS_BUS_SPACE_NORMAL; 215 ga.ga_ioh = MIPS_PHYS_TO_KSEG1(ga.ga_addr); 216 ga.ga_dmat = &sgimips_default_bus_dma_tag; 217 ga.ga_product = -1; 218 219 if (platform.badaddr((void *)ga.ga_ioh, sizeof(uint32_t))) 220 continue; 221 222 if (config_found_sm_loc(self, "gio", NULL, &ga, gio_print, 223 gio_submatch)) { 224 if (ngfx == MAXGFX) 225 panic("gio_attach: MAXGFX"); 226 gfx[ngfx++] = gfx_bases[i].base; 227 } 228 } 229 230 /* 231 * Now attach any GIO expansion cards. 232 * 233 * Be sure to skip any addresses to which a graphics device has 234 * already been attached. 235 */ 236 for (i = 0; slot_bases[i].base != 0; i++) { 237 bool skip = false; 238 239 /* skip slots that don't apply to us */ 240 if (slot_bases[i].mach_type != mach_type) 241 continue; 242 243 if (slot_bases[i].mach_subtype != -1 && 244 slot_bases[i].mach_subtype != mach_subtype) 245 continue; 246 247 for (j = 0; j < ngfx; j++) { 248 if (slot_bases[i].base == gfx[j]) { 249 skip = true; 250 break; 251 } 252 } 253 if (skip) 254 continue; 255 256 ga.ga_slot = slot_bases[i].slot; 257 ga.ga_addr = slot_bases[i].base; 258 ga.ga_iot = SGIMIPS_BUS_SPACE_NORMAL; 259 ga.ga_ioh = MIPS_PHYS_TO_KSEG1(ga.ga_addr); 260 ga.ga_dmat = &sgimips_default_bus_dma_tag; 261 262 if (platform.badaddr((void *)ga.ga_ioh, sizeof(uint32_t))) 263 continue; 264 265 ga.ga_product = bus_space_read_4(ga.ga_iot, ga.ga_ioh, 0); 266 267 config_found_sm_loc(self, "gio", NULL, &ga, gio_print, 268 gio_submatch); 269 } 270 271 config_search_ia(gio_search, self, "gio", &ga); 272 } 273 274 static int 275 gio_print(void *aux, const char *pnp) 276 { 277 struct gio_attach_args *ga = aux; 278 int i = 0; 279 280 /* gfx probe */ 281 if (ga->ga_product == -1) 282 return (QUIET); 283 284 if (pnp != NULL) { 285 int product, revision; 286 287 product = GIO_PRODUCT_PRODUCTID(ga->ga_product); 288 289 if (GIO_PRODUCT_32BIT_ID(ga->ga_product)) 290 revision = GIO_PRODUCT_REVISION(ga->ga_product); 291 else 292 revision = 0; 293 294 while (gio_knowndevs[i].productid != 0) { 295 if (gio_knowndevs[i].productid == product) { 296 aprint_normal("%s", gio_knowndevs[i].product); 297 break; 298 } 299 i++; 300 } 301 302 if (gio_knowndevs[i].productid == 0) 303 aprint_normal("unknown GIO card"); 304 305 aprint_normal(" (product 0x%02x revision 0x%02x) at %s", 306 product, revision, pnp); 307 } 308 309 if (ga->ga_slot != GIOCF_SLOT_DEFAULT) 310 aprint_normal(" slot %d", ga->ga_slot); 311 if (ga->ga_addr != (uint32_t) GIOCF_ADDR_DEFAULT) 312 aprint_normal(" addr 0x%x", ga->ga_addr); 313 314 return UNCONF; 315 } 316 317 static int 318 gio_search(struct device *parent, struct cfdata *cf, 319 const int *ldesc, void *aux) 320 { 321 struct gio_attach_args *ga = aux; 322 323 do { 324 /* Handled by direct configuration, so skip here */ 325 if (cf->cf_loc[GIOCF_ADDR] == GIOCF_ADDR_DEFAULT) 326 return 0; 327 328 ga->ga_slot = cf->cf_loc[GIOCF_SLOT]; 329 ga->ga_addr = cf->cf_loc[GIOCF_ADDR]; 330 ga->ga_iot = 0; 331 ga->ga_ioh = MIPS_PHYS_TO_KSEG1(ga->ga_addr); 332 333 if (config_match(parent, cf, ga) > 0) 334 config_attach(parent, cf, ga, gio_print); 335 } while (cf->cf_fstate == FSTATE_STAR); 336 337 return 0; 338 } 339 340 static int 341 gio_submatch(struct device *parent, struct cfdata *cf, 342 const int *ldesc, void *aux) 343 { 344 struct gio_attach_args *ga = aux; 345 346 if (cf->cf_loc[GIOCF_SLOT] != GIOCF_SLOT_DEFAULT && 347 cf->cf_loc[GIOCF_SLOT] != ga->ga_slot) 348 return 0; 349 350 if (cf->cf_loc[GIOCF_ADDR] != GIOCF_ADDR_DEFAULT && 351 cf->cf_loc[GIOCF_ADDR] != ga->ga_addr) 352 return 0; 353 354 return config_match(parent, cf, aux); 355 } 356 357 int 358 gio_cnattach() 359 { 360 struct gio_attach_args ga; 361 int i; 362 363 for (i = 0; gfx_bases[i].base != 0; i++) { 364 /* skip bases that don't apply to us */ 365 if (gfx_bases[i].mach_type != mach_type) 366 continue; 367 368 if (gfx_bases[i].mach_subtype != -1 && 369 gfx_bases[i].mach_subtype != mach_subtype) 370 continue; 371 372 ga.ga_slot = -1; 373 ga.ga_addr = gfx_bases[i].base; 374 ga.ga_iot = SGIMIPS_BUS_SPACE_NORMAL; 375 ga.ga_ioh = MIPS_PHYS_TO_KSEG1(ga.ga_addr); 376 ga.ga_dmat = &sgimips_default_bus_dma_tag; 377 ga.ga_product = -1; 378 379 if (platform.badaddr((void *)ga.ga_ioh,sizeof(uint32_t))) 380 continue; 381 382 #if (NGRTWO > 0) 383 if (grtwo_cnattach(&ga) == 0) 384 return 0; 385 #endif 386 387 #if (NLIGHT > 0) 388 if (light_cnattach(&ga) == 0) 389 return 0; 390 #endif 391 392 #if (NNEWPORT > 0) 393 if (newport_cnattach(&ga) == 0) 394 return 0; 395 #endif 396 397 } 398 399 return ENXIO; 400 } 401 402 /* 403 * Devices living in the expansion slots must enable or disable some 404 * GIO arbiter settings. This is accomplished via imc(4) or pic(4) 405 * registers, depending on the machine in question. 406 */ 407 int 408 gio_arb_config(int slot, uint32_t flags) 409 { 410 411 if (flags == 0) 412 return (EINVAL); 413 414 if (flags & ~(GIO_ARB_RT | GIO_ARB_LB | GIO_ARB_MST | GIO_ARB_SLV | 415 GIO_ARB_PIPE | GIO_ARB_NOPIPE | GIO_ARB_32BIT | GIO_ARB_64BIT | 416 GIO_ARB_HPC2_32BIT | GIO_ARB_HPC2_64BIT)) 417 return (EINVAL); 418 419 if (((flags & GIO_ARB_RT) && (flags & GIO_ARB_LB)) || 420 ((flags & GIO_ARB_MST) && (flags & GIO_ARB_SLV)) || 421 ((flags & GIO_ARB_PIPE) && (flags & GIO_ARB_NOPIPE)) || 422 ((flags & GIO_ARB_32BIT) && (flags & GIO_ARB_64BIT)) || 423 ((flags & GIO_ARB_HPC2_32BIT) && (flags & GIO_ARB_HPC2_64BIT))) 424 return (EINVAL); 425 426 #if (NPIC > 0) 427 if (mach_type == MACH_SGI_IP12) 428 return (pic_gio32_arb_config(slot, flags)); 429 #endif 430 431 #if (NIMC > 0) 432 if (mach_type == MACH_SGI_IP20 || mach_type == MACH_SGI_IP22) 433 return (imc_gio64_arb_config(slot, flags)); 434 #endif 435 436 return (EINVAL); 437 } 438 439 /* 440 * Establish an interrupt handler for the specified slot. 441 * 442 * Indy and Challenge S have an interrupt per GIO slot. Indigo and Indigo2 443 * share a single interrupt, however. 444 */ 445 void * 446 gio_intr_establish(int slot, int level, int (*func)(void *), void *arg) 447 { 448 int intr; 449 450 switch (mach_type) { 451 case MACH_SGI_IP12: 452 case MACH_SGI_IP20: 453 if (slot == GIO_SLOT_GFX) 454 panic("gio_intr_establish: slot %d", slot); 455 intr = 6; 456 break; 457 458 case MACH_SGI_IP22: 459 if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) { 460 if (slot == GIO_SLOT_EXP1) 461 panic("gio_intr_establish: slot %d", slot); 462 intr = 6; 463 } else { 464 if (slot == GIO_SLOT_GFX) 465 panic("gio_intr_establish: slot %d", slot); 466 intr = (slot == GIO_SLOT_EXP0) ? 22 : 23; 467 } 468 break; 469 470 default: 471 panic("gio_intr_establish: mach_type"); 472 } 473 474 return (cpu_intr_establish(intr, level, func, arg)); 475 } 476 477 const char * 478 gio_product_string(int prid) 479 { 480 int i; 481 482 for (i = 0; gio_knowndevs[i].product != NULL; i++) 483 if (gio_knowndevs[i].productid == prid) 484 return (gio_knowndevs[i].product); 485 486 return (NULL); 487 } 488