1 /* $OpenBSD: gdt_pci.c,v 1.12 2001/07/30 01:28:56 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Niklas Hallqvist. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This driver would not have written if it was not for the hardware donations 34 * from both ICP-Vortex and �ko.neT. I want to thank them for their support. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/queue.h> 43 44 #include <machine/bus.h> 45 #include <machine/endian.h> 46 #include <machine/intr.h> 47 48 #include <scsi/scsi_all.h> 49 #include <scsi/scsiconf.h> 50 51 #include <dev/pci/pcidevs.h> 52 #include <dev/pci/pcireg.h> 53 #include <dev/pci/pcivar.h> 54 55 #include <dev/ic/gdtreg.h> 56 #include <dev/ic/gdtvar.h> 57 58 /* Product numbers for Fibre-Channel are greater than or equal to 0x200 */ 59 #define GDT_PCI_PRODUCT_FC 0x200 60 61 /* Mapping registers for various areas */ 62 #define GDT_PCI_DPMEM 0x10 63 #define GDT_PCINEW_IOMEM 0x10 64 #define GDT_PCINEW_IO 0x14 65 #define GDT_PCINEW_DPMEM 0x18 66 67 /* PCI SRAM structure */ 68 #define GDT_MAGIC 0x00 /* u_int32_t, controller ID from BIOS */ 69 #define GDT_NEED_DEINIT 0x04 /* u_int16_t, switch between BIOS/driver */ 70 #define GDT_SWITCH_SUPPORT 0x06 /* u_int8_t, see GDT_NEED_DEINIT */ 71 #define GDT_OS_USED 0x10 /* u_int8_t [16], OS code per service */ 72 #define GDT_FW_MAGIC 0x3c /* u_int8_t, controller ID from firmware */ 73 #define GDT_SRAM_SZ 0x40 74 75 /* DPRAM PCI controllers */ 76 #define GDT_DPR_IF 0x00 /* interface area */ 77 #define GDT_6SR (0xff0 - GDT_SRAM_SZ) 78 #define GDT_SEMA1 0xff1 /* volatile u_int8_t, command semaphore */ 79 #define GDT_IRQEN 0xff5 /* u_int8_t, board interrupts enable */ 80 #define GDT_EVENT 0xff8 /* u_int8_t, release event */ 81 #define GDT_IRQDEL 0xffc /* u_int8_t, acknowledge board interrupt */ 82 #define GDT_DPRAM_SZ 0x1000 83 84 /* PLX register structure (new PCI controllers) */ 85 #define GDT_CFG_REG 0x00 /* u_int8_t, DPRAM cfg. (2: < 1MB, 0: any) */ 86 #define GDT_SEMA0_REG 0x40 /* volatile u_int8_t, command semaphore */ 87 #define GDT_SEMA1_REG 0x41 /* volatile u_int8_t, status semaphore */ 88 #define GDT_PLX_STATUS 0x44 /* volatile u_int16_t, command status */ 89 #define GDT_PLX_SERVICE 0x46 /* u_int16_t, service */ 90 #define GDT_PLX_INFO 0x48 /* u_int32_t [2], additional info */ 91 #define GDT_LDOOR_REG 0x60 /* u_int8_t, PCI to local doorbell */ 92 #define GDT_EDOOR_REG 0x64 /* volatile u_int8_t, local to PCI doorbell */ 93 #define GDT_CONTROL0 0x68 /* u_int8_t, control0 register (unused) */ 94 #define GDT_CONTROL1 0x69 /* u_int8_t, board interrupts enable */ 95 #define GDT_PLX_SZ 0x80 96 97 /* DPRAM new PCI controllers */ 98 #define GDT_IC 0x00 /* interface */ 99 #define GDT_PCINEW_6SR (0x4000 - GDT_SRAM_SZ) 100 /* SRAM structure */ 101 #define GDT_PCINEW_SZ 0x4000 102 103 /* i960 register structure (PCI MPR controllers) */ 104 #define GDT_MPR_SEMA0 0x10 /* volatile u_int8_t, command semaphore */ 105 #define GDT_MPR_SEMA1 0x12 /* volatile u_int8_t, status semaphore */ 106 #define GDT_MPR_STATUS 0x14 /* volatile u_int16_t, command status */ 107 #define GDT_MPR_SERVICE 0x16 /* u_int16_t, service */ 108 #define GDT_MPR_INFO 0x18 /* u_int32_t [2], additional info */ 109 #define GDT_MPR_LDOOR 0x20 /* u_int8_t, PCI to local doorbell */ 110 #define GDT_MPR_EDOOR 0x2c /* volatile u_int8_t, locl to PCI doorbell */ 111 #define GDT_EDOOR_EN 0x34 /* u_int8_t, board interrupts enable */ 112 #define GDT_I960_SZ 0x1000 113 114 /* DPRAM PCI MPR controllers */ 115 #define GDT_I960R 0x00 /* 4KB i960 registers */ 116 #define GDT_MPR_IC GDT_I960_SZ 117 /* interface area */ 118 #define GDT_MPR_6SR (GDT_I960_SZ + 0x3000 - GDT_SRAM_SZ) 119 /* SRAM structure */ 120 #define GDT_MPR_SZ 0x4000 121 122 int gdt_pci_probe __P((struct device *, void *, void *)); 123 void gdt_pci_attach __P((struct device *, struct device *, void *)); 124 void gdt_pci_enable_intr __P((struct gdt_softc *)); 125 126 void gdt_pci_copy_cmd __P((struct gdt_softc *, struct gdt_ccb *)); 127 u_int8_t gdt_pci_get_status __P((struct gdt_softc *)); 128 void gdt_pci_intr __P((struct gdt_softc *, struct gdt_intr_ctx *)); 129 void gdt_pci_release_event __P((struct gdt_softc *, struct gdt_ccb *)); 130 void gdt_pci_set_sema0 __P((struct gdt_softc *)); 131 int gdt_pci_test_busy __P((struct gdt_softc *)); 132 133 void gdt_pcinew_copy_cmd __P((struct gdt_softc *, struct gdt_ccb *)); 134 u_int8_t gdt_pcinew_get_status __P((struct gdt_softc *)); 135 void gdt_pcinew_intr __P((struct gdt_softc *, struct gdt_intr_ctx *)); 136 void gdt_pcinew_release_event __P((struct gdt_softc *, struct gdt_ccb *)); 137 void gdt_pcinew_set_sema0 __P((struct gdt_softc *)); 138 int gdt_pcinew_test_busy __P((struct gdt_softc *)); 139 140 void gdt_mpr_copy_cmd __P((struct gdt_softc *, struct gdt_ccb *)); 141 u_int8_t gdt_mpr_get_status __P((struct gdt_softc *)); 142 void gdt_mpr_intr __P((struct gdt_softc *, struct gdt_intr_ctx *)); 143 void gdt_mpr_release_event __P((struct gdt_softc *, struct gdt_ccb *)); 144 void gdt_mpr_set_sema0 __P((struct gdt_softc *)); 145 int gdt_mpr_test_busy __P((struct gdt_softc *)); 146 147 struct cfattach gdt_pci_ca = { 148 sizeof (struct gdt_softc), gdt_pci_probe, gdt_pci_attach 149 }; 150 151 int 152 gdt_pci_probe(parent, match, aux) 153 struct device *parent; 154 void *match, *aux; 155 { 156 struct pci_attach_args *pa = aux; 157 158 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX && 159 PCI_PRODUCT(pa->pa_id) >= 0x100 && PCI_PRODUCT(pa->pa_id) <= 0x2ff) 160 return (1); 161 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 162 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GDT_RAID2) 163 return (1); 164 return (0); 165 } 166 167 void 168 gdt_pci_attach(parent, self, aux) 169 struct device *parent, *self; 170 void *aux; 171 { 172 struct pci_attach_args *pa = aux; 173 struct gdt_softc *gdt = (void *)self; 174 bus_space_tag_t dpmemt, iomemt, iot; 175 bus_space_handle_t dpmemh, iomemh, ioh; 176 bus_addr_t dpmembase, iomembase, iobase; 177 bus_size_t dpmemsize, iomemsize, iosize; 178 u_int16_t prod; 179 u_int32_t status = 0; 180 #define DPMEM_MAPPED 1 181 #define IOMEM_MAPPED 2 182 #define IO_MAPPED 4 183 #define INTR_ESTABLISHED 8 184 int retries; 185 u_int8_t protocol; 186 pci_intr_handle_t ih; 187 const char *intrstr; 188 189 printf(": "); 190 191 gdt->sc_class = 0; 192 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX) { 193 prod = PCI_PRODUCT(pa->pa_id); 194 switch (prod) { 195 case PCI_PRODUCT_VORTEX_GDT_60x0: 196 case PCI_PRODUCT_VORTEX_GDT_6000B: 197 gdt->sc_class = GDT_PCI; 198 break; 199 200 case PCI_PRODUCT_VORTEX_GDT_6x10: 201 case PCI_PRODUCT_VORTEX_GDT_6x20: 202 case PCI_PRODUCT_VORTEX_GDT_6530: 203 case PCI_PRODUCT_VORTEX_GDT_6550: 204 case PCI_PRODUCT_VORTEX_GDT_6x17: 205 case PCI_PRODUCT_VORTEX_GDT_6x27: 206 case PCI_PRODUCT_VORTEX_GDT_6537: 207 case PCI_PRODUCT_VORTEX_GDT_6557: 208 case PCI_PRODUCT_VORTEX_GDT_6x15: 209 case PCI_PRODUCT_VORTEX_GDT_6x25: 210 case PCI_PRODUCT_VORTEX_GDT_6535: 211 case PCI_PRODUCT_VORTEX_GDT_6555: 212 gdt->sc_class = GDT_PCINEW; 213 break; 214 215 case PCI_PRODUCT_VORTEX_GDT_6x17RP: 216 case PCI_PRODUCT_VORTEX_GDT_6x27RP: 217 case PCI_PRODUCT_VORTEX_GDT_6537RP: 218 case PCI_PRODUCT_VORTEX_GDT_6557RP: 219 case PCI_PRODUCT_VORTEX_GDT_6x11RP: 220 case PCI_PRODUCT_VORTEX_GDT_6x21RP: 221 case PCI_PRODUCT_VORTEX_GDT_6x17RD: 222 case PCI_PRODUCT_VORTEX_GDT_6x27RD: 223 case PCI_PRODUCT_VORTEX_GDT_6537RD: 224 case PCI_PRODUCT_VORTEX_GDT_6557RD: 225 case PCI_PRODUCT_VORTEX_GDT_6x11RD: 226 case PCI_PRODUCT_VORTEX_GDT_6x21RD: 227 case PCI_PRODUCT_VORTEX_GDT_6x18RD: 228 case PCI_PRODUCT_VORTEX_GDT_6x28RD: 229 case PCI_PRODUCT_VORTEX_GDT_6x38RD: 230 case PCI_PRODUCT_VORTEX_GDT_6x58RD: 231 case PCI_PRODUCT_VORTEX_GDT_6518RS: 232 case PCI_PRODUCT_VORTEX_GDT_7x18RN: 233 case PCI_PRODUCT_VORTEX_GDT_7x28RN: 234 case PCI_PRODUCT_VORTEX_GDT_7x38RN: 235 case PCI_PRODUCT_VORTEX_GDT_7x58RN: 236 case PCI_PRODUCT_VORTEX_GDT_6x19RD: 237 case PCI_PRODUCT_VORTEX_GDT_6x29RD: 238 case PCI_PRODUCT_VORTEX_GDT_7x19RN: 239 case PCI_PRODUCT_VORTEX_GDT_7x29RN: 240 case PCI_PRODUCT_VORTEX_GDT_7x43RN: 241 gdt->sc_class = GDT_MPR; 242 } 243 244 /* If we don't recognize it, determine class heuristically. */ 245 if (gdt->sc_class == 0) 246 gdt->sc_class = prod < 0x100 ? GDT_PCINEW : GDT_MPR; 247 248 if (prod >= GDT_PCI_PRODUCT_FC) 249 gdt->sc_class |= GDT_FC; 250 251 } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) { 252 gdt->sc_class = GDT_MPR; 253 } 254 255 if (pci_mapreg_map(pa, 256 GDT_CLASS(gdt) == GDT_PCINEW ? GDT_PCINEW_DPMEM : GDT_PCI_DPMEM, 257 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt, 258 &dpmemh, &dpmembase, &dpmemsize, 0)) { 259 if (pci_mapreg_map(pa, 260 GDT_CLASS(gdt) == GDT_PCINEW ? GDT_PCINEW_DPMEM : 261 GDT_PCI_DPMEM, 262 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0, 263 &dpmemt,&dpmemh, &dpmembase, &dpmemsize, 0)) { 264 printf("cannot map DPMEM\n"); 265 goto bail_out; 266 } 267 } 268 status |= DPMEM_MAPPED; 269 gdt->sc_dpmemt = dpmemt; 270 gdt->sc_dpmemh = dpmemh; 271 gdt->sc_dpmembase = dpmembase; 272 gdt->sc_dmat = pa->pa_dmat; 273 274 /* 275 * The GDT_PCINEW series also has two other regions to map. 276 */ 277 if (GDT_CLASS(gdt) == GDT_PCINEW) { 278 if (pci_mapreg_map(pa, GDT_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM, 279 0, &iomemt, &iomemh, &iomembase, &iomemsize, 0)) { 280 printf("cannot map memory mapped I/O ports\n"); 281 goto bail_out; 282 } 283 status |= IOMEM_MAPPED; 284 285 if (pci_mapreg_map(pa, GDT_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0, 286 &iot, &ioh, &iobase, &iosize, 0)) { 287 printf("cannot map I/O ports\n"); 288 goto bail_out; 289 } 290 status |= IO_MAPPED; 291 gdt->sc_iot = iot; 292 gdt->sc_ioh = ioh; 293 gdt->sc_iobase = iobase; 294 } 295 296 switch (GDT_CLASS(gdt)) { 297 case GDT_PCI: 298 bus_space_set_region_4(dpmemt, dpmemh, 0, htole32(0), 299 GDT_DPR_IF_SZ >> 2); 300 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { 301 printf("cannot write to DPMEM\n"); 302 goto bail_out; 303 } 304 305 #if 0 306 /* disable board interrupts, deinit services */ 307 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 308 gdth_writeb(0x00, &dp6_ptr->io.irqen);; 309 gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status); 310 gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); 311 312 gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); 313 gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); 314 gdth_writeb(0, &dp6_ptr->io.event); 315 retries = INIT_RETRIES; 316 gdth_delay(20); 317 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { 318 if (--retries == 0) { 319 printk("initialization error (DEINIT failed)\n"); 320 gdth_munmap(ha->brd); 321 return 0; 322 } 323 gdth_delay(1); 324 } 325 prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]); 326 gdth_writeb(0, &dp6_ptr->u.ic.S_Status); 327 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 328 if (prot_ver != PROTOCOL_VERSION) { 329 printk("illegal protocol version\n"); 330 gdth_munmap(ha->brd); 331 return 0; 332 } 333 334 ha->type = GDT_PCI; 335 ha->ic_all_size = sizeof(dp6_ptr->u); 336 337 /* special command to controller BIOS */ 338 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); 339 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); 340 gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); 341 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); 342 gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); 343 gdth_writeb(0, &dp6_ptr->io.event); 344 retries = INIT_RETRIES; 345 gdth_delay(20); 346 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { 347 if (--retries == 0) { 348 printk("initialization error\n"); 349 gdth_munmap(ha->brd); 350 return 0; 351 } 352 gdth_delay(1); 353 } 354 gdth_writeb(0, &dp6_ptr->u.ic.S_Status); 355 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 356 #endif 357 358 gdt->sc_ic_all_size = GDT_DPRAM_SZ; 359 360 gdt->sc_copy_cmd = gdt_pci_copy_cmd; 361 gdt->sc_get_status = gdt_pci_get_status; 362 gdt->sc_intr = gdt_pci_intr; 363 gdt->sc_release_event = gdt_pci_release_event; 364 gdt->sc_set_sema0 = gdt_pci_set_sema0; 365 gdt->sc_test_busy = gdt_pci_test_busy; 366 367 break; 368 369 case GDT_PCINEW: 370 bus_space_set_region_4(dpmemt, dpmemh, 0, htole32(0), 371 GDT_DPR_IF_SZ >> 2); 372 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { 373 printf("cannot write to DPMEM\n"); 374 goto bail_out; 375 } 376 377 #if 0 378 /* disable board interrupts, deinit services */ 379 outb(0x00,PTR2USHORT(&ha->plx->control1)); 380 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); 381 382 gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); 383 gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); 384 385 gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); 386 gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); 387 388 outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); 389 390 retries = INIT_RETRIES; 391 gdth_delay(20); 392 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { 393 if (--retries == 0) { 394 printk("initialization error (DEINIT failed)\n"); 395 gdth_munmap(ha->brd); 396 return 0; 397 } 398 gdth_delay(1); 399 } 400 prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); 401 gdth_writeb(0, &dp6c_ptr->u.ic.Status); 402 if (prot_ver != PROTOCOL_VERSION) { 403 printk("illegal protocol version\n"); 404 gdth_munmap(ha->brd); 405 return 0; 406 } 407 408 ha->type = GDT_PCINEW; 409 ha->ic_all_size = sizeof(dp6c_ptr->u); 410 411 /* special command to controller BIOS */ 412 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); 413 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); 414 gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); 415 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); 416 gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); 417 418 outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); 419 420 retries = INIT_RETRIES; 421 gdth_delay(20); 422 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { 423 if (--retries == 0) { 424 printk("initialization error\n"); 425 gdth_munmap(ha->brd); 426 return 0; 427 } 428 gdth_delay(1); 429 } 430 gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); 431 #endif 432 433 gdt->sc_ic_all_size = GDT_PCINEW_SZ; 434 435 gdt->sc_copy_cmd = gdt_pcinew_copy_cmd; 436 gdt->sc_get_status = gdt_pcinew_get_status; 437 gdt->sc_intr = gdt_pcinew_intr; 438 gdt->sc_release_event = gdt_pcinew_release_event; 439 gdt->sc_set_sema0 = gdt_pcinew_set_sema0; 440 gdt->sc_test_busy = gdt_pcinew_test_busy; 441 442 break; 443 444 case GDT_MPR: 445 bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC, 446 htole32(GDT_MPR_MAGIC)); 447 if (bus_space_read_4(dpmemt, dpmemh, GDT_MPR_IC) != 448 htole32(GDT_MPR_MAGIC)) { 449 printf("cannot access DPMEM at 0x%x (shadowed?)\n", 450 dpmembase); 451 goto bail_out; 452 } 453 454 /* 455 * XXX Here the Linux driver has a weird remapping logic I 456 * don't understand. My controller does not need it, and I 457 * cannot see what purpose it serves, therefore I did not 458 * do anything similar. 459 */ 460 461 bus_space_set_region_4(dpmemt, dpmemh, GDT_I960_SZ, htole32(0), 462 GDT_DPR_IF_SZ >> 2); 463 464 /* Disable everything */ 465 bus_space_write_1(dpmemt, dpmemh, GDT_EDOOR_EN, 466 bus_space_read_1(dpmemt, dpmemh, GDT_EDOOR_EN) | 4); 467 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_EDOOR, 0xff); 468 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 469 0); 470 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_CMD_INDEX, 471 0); 472 473 bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO, 474 htole32(dpmembase)); 475 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 476 0xff); 477 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_LDOOR, 1); 478 479 DELAY(20); 480 retries = GDT_RETRIES; 481 while (bus_space_read_1(dpmemt, dpmemh, 482 GDT_MPR_IC + GDT_S_STATUS) != 0xff) { 483 if (--retries == 0) { 484 printf("DEINIT failed\n"); 485 goto bail_out; 486 } 487 DELAY(1); 488 } 489 490 protocol = (u_int8_t)letoh32(bus_space_read_4(dpmemt, dpmemh, 491 GDT_MPR_IC + GDT_S_INFO)); 492 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 493 0); 494 if (protocol != GDT_PROTOCOL_VERSION) { 495 printf("unsupported protocol %d\n", protocol); 496 goto bail_out; 497 } 498 499 /* special commnd to controller BIOS */ 500 bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO, 501 htole32(0)); 502 bus_space_write_4(dpmemt, dpmemh, 503 GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0)); 504 bus_space_write_4(dpmemt, dpmemh, 505 GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), 506 htole32(1)); 507 bus_space_write_4(dpmemt, dpmemh, 508 GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), 509 htole32(0)); 510 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 511 0xfe); 512 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_LDOOR, 1); 513 514 DELAY(20); 515 retries = GDT_RETRIES; 516 while (bus_space_read_1(dpmemt, dpmemh, 517 GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { 518 if (--retries == 0) { 519 printf("initialization error\n"); 520 goto bail_out; 521 } 522 DELAY(1); 523 } 524 525 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 526 0); 527 528 gdt->sc_ic_all_size = GDT_MPR_SZ; 529 530 gdt->sc_copy_cmd = gdt_mpr_copy_cmd; 531 gdt->sc_get_status = gdt_mpr_get_status; 532 gdt->sc_intr = gdt_mpr_intr; 533 gdt->sc_release_event = gdt_mpr_release_event; 534 gdt->sc_set_sema0 = gdt_mpr_set_sema0; 535 gdt->sc_test_busy = gdt_mpr_test_busy; 536 } 537 538 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 539 pa->pa_intrline, &ih)) { 540 printf("couldn't map interrupt\n"); 541 goto bail_out; 542 } 543 intrstr = pci_intr_string(pa->pa_pc, ih); 544 gdt->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, gdt_intr, gdt, 545 gdt->sc_dev.dv_xname); 546 if (gdt->sc_ih == NULL) { 547 printf("couldn't establish interrupt"); 548 if (intrstr != NULL) 549 printf(" at %s", intrstr); 550 printf("\n"); 551 goto bail_out; 552 } 553 status |= INTR_ESTABLISHED; 554 if (intrstr != NULL) 555 printf("%s ", intrstr); 556 557 if (gdt_attach(gdt)) 558 goto bail_out; 559 560 gdt_pci_enable_intr(gdt); 561 562 return; 563 564 bail_out: 565 if (status & DPMEM_MAPPED) 566 bus_space_unmap(dpmemt, dpmemh, dpmemsize); 567 if (status & IOMEM_MAPPED) 568 bus_space_unmap(iomemt, iomemh, iomembase); 569 if (status & IO_MAPPED) 570 bus_space_unmap(iot, ioh, iosize); 571 if (status & INTR_ESTABLISHED) 572 pci_intr_disestablish(pa->pa_pc, gdt->sc_ih); 573 return; 574 } 575 576 /* Enable interrupts */ 577 void 578 gdt_pci_enable_intr(gdt) 579 struct gdt_softc *gdt; 580 { 581 GDT_DPRINTF(GDT_D_INTR, ("gdt_pci_enable_intr(%p) ", gdt)); 582 583 switch(GDT_CLASS(gdt)) { 584 case GDT_PCI: 585 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_IRQDEL, 586 1); 587 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 588 GDT_CMD_INDEX, 0); 589 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_IRQEN, 590 1); 591 break; 592 593 case GDT_PCINEW: 594 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_EDOOR_REG, 595 0xff); 596 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_CONTROL1, 3); 597 break; 598 599 case GDT_MPR: 600 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 601 GDT_MPR_EDOOR, 0xff); 602 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, 603 bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 604 GDT_EDOOR_EN) & ~4); 605 break; 606 } 607 } 608 609 /* 610 * "old" PCI controller-specific functions 611 */ 612 613 void 614 gdt_pci_copy_cmd(gdt, ccb) 615 struct gdt_softc *gdt; 616 struct gdt_ccb *ccb; 617 { 618 /* XXX Not yet implemented */ 619 } 620 621 u_int8_t 622 gdt_pci_get_status(gdt) 623 struct gdt_softc *gdt; 624 { 625 /* XXX Not yet implemented */ 626 return (0); 627 } 628 629 void 630 gdt_pci_intr(gdt, ctx) 631 struct gdt_softc *gdt; 632 struct gdt_intr_ctx *ctx; 633 { 634 /* XXX Not yet implemented */ 635 } 636 637 void 638 gdt_pci_release_event(gdt, ccb) 639 struct gdt_softc *gdt; 640 struct gdt_ccb *ccb; 641 { 642 /* XXX Not yet implemented */ 643 } 644 645 void 646 gdt_pci_set_sema0(gdt) 647 struct gdt_softc *gdt; 648 { 649 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_SEMA0, 1); 650 } 651 652 int 653 gdt_pci_test_busy(gdt) 654 struct gdt_softc *gdt; 655 { 656 /* XXX Not yet implemented */ 657 return (0); 658 } 659 660 /* 661 * "new" PCI controller-specific functions 662 */ 663 664 void 665 gdt_pcinew_copy_cmd(gdt, ccb) 666 struct gdt_softc *gdt; 667 struct gdt_ccb *ccb; 668 { 669 /* XXX Not yet implemented */ 670 } 671 672 u_int8_t 673 gdt_pcinew_get_status(gdt) 674 struct gdt_softc *gdt; 675 { 676 /* XXX Not yet implemented */ 677 return (0); 678 } 679 680 void 681 gdt_pcinew_intr(gdt, ctx) 682 struct gdt_softc *gdt; 683 struct gdt_intr_ctx *ctx; 684 { 685 /* XXX Not yet implemented */ 686 } 687 688 void 689 gdt_pcinew_release_event(gdt, ccb) 690 struct gdt_softc *gdt; 691 struct gdt_ccb *ccb; 692 { 693 /* XXX Not yet implemented */ 694 } 695 696 void 697 gdt_pcinew_set_sema0(gdt) 698 struct gdt_softc *gdt; 699 { 700 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_SEMA0_REG, 1); 701 } 702 703 int 704 gdt_pcinew_test_busy(gdt) 705 struct gdt_softc *gdt; 706 { 707 /* XXX Not yet implemented */ 708 return (0); 709 } 710 711 /* 712 * MPR PCI controller-specific functions 713 */ 714 715 void 716 gdt_mpr_copy_cmd(gdt, ccb) 717 struct gdt_softc *gdt; 718 struct gdt_ccb *ccb; 719 { 720 u_int16_t cp_count = roundup(gdt->sc_cmd_len, sizeof (u_int32_t)); 721 u_int16_t dp_offset = gdt->sc_cmd_off; 722 u_int16_t cmd_no = gdt->sc_cmd_cnt++; 723 724 GDT_DPRINTF(GDT_D_CMD, ("gdt_mpr_copy_cmd(%p) ", gdt)); 725 726 gdt->sc_cmd_off += cp_count; 727 728 bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, 729 GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET, 730 htole16(GDT_DPMEM_COMMAND_OFFSET + dp_offset)); 731 bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, 732 GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID, 733 htole16(ccb->gc_service)); 734 bus_space_write_raw_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, 735 GDT_MPR_IC + GDT_DPR_CMD + dp_offset, gdt->sc_cmd, cp_count); 736 } 737 738 u_int8_t 739 gdt_mpr_get_status(gdt) 740 struct gdt_softc *gdt; 741 { 742 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_get_status(%p) ", gdt)); 743 744 return bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR); 745 } 746 747 void 748 gdt_mpr_intr(gdt, ctx) 749 struct gdt_softc *gdt; 750 struct gdt_intr_ctx *ctx; 751 { 752 GDT_DPRINTF(GDT_D_INTR, ("gdt_mpr_intr(%p) ", gdt)); 753 754 if (ctx->istatus & 0x80) { /* error flag */ 755 ctx->istatus &= ~0x80; 756 ctx->cmd_status = bus_space_read_2(gdt->sc_dpmemt, 757 gdt->sc_dpmemh, GDT_MPR_STATUS); 758 if (ctx->istatus == GDT_ASYNCINDEX) { 759 ctx->service = bus_space_read_2(gdt->sc_dpmemt, 760 gdt->sc_dpmemh, GDT_MPR_SERVICE); 761 ctx->info2 = bus_space_read_4(gdt->sc_dpmemt, 762 gdt->sc_dpmemh, GDT_MPR_INFO + sizeof (u_int32_t)); 763 } 764 } else /* no error */ 765 ctx->cmd_status = GDT_S_OK; 766 767 ctx->info = 768 bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_INFO); 769 770 if (gdt_polling) /* init. -> more info */ 771 ctx->info2 = bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, 772 GDT_MPR_INFO + sizeof (u_int32_t)); 773 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); 774 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA1, 0); 775 } 776 777 void 778 gdt_mpr_release_event(gdt, ccb) 779 struct gdt_softc *gdt; 780 struct gdt_ccb *ccb; 781 { 782 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_release_event(%p) ", gdt)); 783 784 if (gdt_dec16(gdt->sc_cmd + GDT_CMD_OPCODE) == GDT_INIT) 785 ccb->gc_service |= 0x80; 786 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); 787 } 788 789 void 790 gdt_mpr_set_sema0(gdt) 791 struct gdt_softc *gdt; 792 { 793 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_set_sema0(%p) ", gdt)); 794 795 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA0, 1); 796 } 797 798 int 799 gdt_mpr_test_busy(gdt) 800 struct gdt_softc *gdt; 801 { 802 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_test_busy(%p) ", gdt)); 803 804 return (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 805 GDT_MPR_SEMA0) & 1); 806 } 807