1 /* $OpenBSD: gdt_pci.c,v 1.17 2002/06/11 14:41:35 niklas 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(struct device *, void *, void *); 123 void gdt_pci_attach(struct device *, struct device *, void *); 124 void gdt_pci_enable_intr(struct gdt_softc *); 125 126 void gdt_pci_copy_cmd(struct gdt_softc *, struct gdt_ccb *); 127 u_int8_t gdt_pci_get_status(struct gdt_softc *); 128 void gdt_pci_intr(struct gdt_softc *, struct gdt_intr_ctx *); 129 void gdt_pci_release_event(struct gdt_softc *, struct gdt_ccb *); 130 void gdt_pci_set_sema0(struct gdt_softc *); 131 int gdt_pci_test_busy(struct gdt_softc *); 132 133 void gdt_pcinew_copy_cmd(struct gdt_softc *, struct gdt_ccb *); 134 u_int8_t gdt_pcinew_get_status(struct gdt_softc *); 135 void gdt_pcinew_intr(struct gdt_softc *, struct gdt_intr_ctx *); 136 void gdt_pcinew_release_event(struct gdt_softc *, struct gdt_ccb *); 137 void gdt_pcinew_set_sema0(struct gdt_softc *); 138 int gdt_pcinew_test_busy(struct gdt_softc *); 139 140 void gdt_mpr_copy_cmd(struct gdt_softc *, struct gdt_ccb *); 141 u_int8_t gdt_mpr_get_status(struct gdt_softc *); 142 void gdt_mpr_intr(struct gdt_softc *, struct gdt_intr_ctx *); 143 void gdt_mpr_release_event(struct gdt_softc *, struct gdt_ccb *); 144 void gdt_mpr_set_sema0(struct gdt_softc *); 145 int gdt_mpr_test_busy(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) <= 0x300) 160 return (1); 161 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 162 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GDT_RAID1 || 163 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GDT_RAID2)) 164 return (1); 165 return (0); 166 } 167 168 void 169 gdt_pci_attach(parent, self, aux) 170 struct device *parent, *self; 171 void *aux; 172 { 173 struct pci_attach_args *pa = aux; 174 struct gdt_softc *gdt = (void *)self; 175 bus_space_tag_t dpmemt, iomemt, iot; 176 bus_space_handle_t dpmemh, iomemh, ioh; 177 bus_addr_t dpmembase, iomembase, iobase; 178 bus_size_t dpmemsize, iomemsize, iosize; 179 u_int16_t prod; 180 u_int32_t status = 0; 181 #define DPMEM_MAPPED 1 182 #define IOMEM_MAPPED 2 183 #define IO_MAPPED 4 184 #define INTR_ESTABLISHED 8 185 int retries; 186 u_int8_t protocol; 187 pci_intr_handle_t ih; 188 const char *intrstr; 189 190 printf(": "); 191 192 gdt->sc_class = 0; 193 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX) { 194 prod = PCI_PRODUCT(pa->pa_id); 195 switch (prod) { 196 case PCI_PRODUCT_VORTEX_GDT_60x0: 197 case PCI_PRODUCT_VORTEX_GDT_6000B: 198 gdt->sc_class = GDT_PCI; 199 break; 200 201 case PCI_PRODUCT_VORTEX_GDT_6x10: 202 case PCI_PRODUCT_VORTEX_GDT_6x20: 203 case PCI_PRODUCT_VORTEX_GDT_6530: 204 case PCI_PRODUCT_VORTEX_GDT_6550: 205 case PCI_PRODUCT_VORTEX_GDT_6x17: 206 case PCI_PRODUCT_VORTEX_GDT_6x27: 207 case PCI_PRODUCT_VORTEX_GDT_6537: 208 case PCI_PRODUCT_VORTEX_GDT_6557: 209 case PCI_PRODUCT_VORTEX_GDT_6x15: 210 case PCI_PRODUCT_VORTEX_GDT_6x25: 211 case PCI_PRODUCT_VORTEX_GDT_6535: 212 case PCI_PRODUCT_VORTEX_GDT_6555: 213 gdt->sc_class = GDT_PCINEW; 214 break; 215 216 case PCI_PRODUCT_VORTEX_GDT_6x17RP: 217 case PCI_PRODUCT_VORTEX_GDT_6x27RP: 218 case PCI_PRODUCT_VORTEX_GDT_6537RP: 219 case PCI_PRODUCT_VORTEX_GDT_6557RP: 220 case PCI_PRODUCT_VORTEX_GDT_6x11RP: 221 case PCI_PRODUCT_VORTEX_GDT_6x21RP: 222 case PCI_PRODUCT_VORTEX_GDT_6x17RD: 223 case PCI_PRODUCT_VORTEX_GDT_6x27RD: 224 case PCI_PRODUCT_VORTEX_GDT_6537RD: 225 case PCI_PRODUCT_VORTEX_GDT_6557RD: 226 case PCI_PRODUCT_VORTEX_GDT_6x11RD: 227 case PCI_PRODUCT_VORTEX_GDT_6x21RD: 228 case PCI_PRODUCT_VORTEX_GDT_6x18RD: 229 case PCI_PRODUCT_VORTEX_GDT_6x28RD: 230 case PCI_PRODUCT_VORTEX_GDT_6x38RD: 231 case PCI_PRODUCT_VORTEX_GDT_6x58RD: 232 case PCI_PRODUCT_VORTEX_GDT_6518RS: 233 case PCI_PRODUCT_VORTEX_GDT_7x18RN: 234 case PCI_PRODUCT_VORTEX_GDT_7x28RN: 235 case PCI_PRODUCT_VORTEX_GDT_7x38RN: 236 case PCI_PRODUCT_VORTEX_GDT_7x58RN: 237 case PCI_PRODUCT_VORTEX_GDT_6x19RD: 238 case PCI_PRODUCT_VORTEX_GDT_6x29RD: 239 case PCI_PRODUCT_VORTEX_GDT_7x19RN: 240 case PCI_PRODUCT_VORTEX_GDT_7x29RN: 241 case PCI_PRODUCT_VORTEX_GDT_7x43RN: 242 gdt->sc_class = GDT_MPR; 243 } 244 245 /* If we don't recognize it, determine class heuristically. */ 246 if (gdt->sc_class == 0) 247 gdt->sc_class = prod < 0x100 ? GDT_PCINEW : GDT_MPR; 248 249 if (prod >= GDT_PCI_PRODUCT_FC) 250 gdt->sc_class |= GDT_FC; 251 252 } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) { 253 gdt->sc_class = GDT_MPR; 254 } 255 256 if (pci_mapreg_map(pa, 257 GDT_CLASS(gdt) == GDT_PCINEW ? GDT_PCINEW_DPMEM : GDT_PCI_DPMEM, 258 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt, 259 &dpmemh, &dpmembase, &dpmemsize, 0)) { 260 if (pci_mapreg_map(pa, 261 GDT_CLASS(gdt) == GDT_PCINEW ? GDT_PCINEW_DPMEM : 262 GDT_PCI_DPMEM, 263 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0, 264 &dpmemt,&dpmemh, &dpmembase, &dpmemsize, 0)) { 265 printf("cannot map DPMEM\n"); 266 goto bail_out; 267 } 268 } 269 status |= DPMEM_MAPPED; 270 gdt->sc_dpmemt = dpmemt; 271 gdt->sc_dpmemh = dpmemh; 272 gdt->sc_dpmembase = dpmembase; 273 gdt->sc_dmat = pa->pa_dmat; 274 275 /* 276 * The GDT_PCINEW series also has two other regions to map. 277 */ 278 if (GDT_CLASS(gdt) == GDT_PCINEW) { 279 if (pci_mapreg_map(pa, GDT_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM, 280 0, &iomemt, &iomemh, &iomembase, &iomemsize, 0)) { 281 printf("cannot map memory mapped I/O ports\n"); 282 goto bail_out; 283 } 284 status |= IOMEM_MAPPED; 285 286 if (pci_mapreg_map(pa, GDT_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0, 287 &iot, &ioh, &iobase, &iosize, 0)) { 288 printf("cannot map I/O ports\n"); 289 goto bail_out; 290 } 291 status |= IO_MAPPED; 292 gdt->sc_iot = iot; 293 gdt->sc_ioh = ioh; 294 gdt->sc_iobase = iobase; 295 } 296 297 switch (GDT_CLASS(gdt)) { 298 case GDT_PCI: 299 bus_space_set_region_4(dpmemt, dpmemh, 0, 0, 300 GDT_DPR_IF_SZ >> 2); 301 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { 302 printf("cannot write to DPMEM\n"); 303 goto bail_out; 304 } 305 306 #if 0 307 /* disable board interrupts, deinit services */ 308 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 309 gdth_writeb(0x00, &dp6_ptr->io.irqen);; 310 gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status); 311 gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); 312 313 gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); 314 gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); 315 gdth_writeb(0, &dp6_ptr->io.event); 316 retries = INIT_RETRIES; 317 gdth_delay(20); 318 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { 319 if (--retries == 0) { 320 printk("initialization error (DEINIT failed)\n"); 321 gdth_munmap(ha->brd); 322 return 0; 323 } 324 gdth_delay(1); 325 } 326 prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]); 327 gdth_writeb(0, &dp6_ptr->u.ic.S_Status); 328 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 329 if (prot_ver != PROTOCOL_VERSION) { 330 printk("illegal protocol version\n"); 331 gdth_munmap(ha->brd); 332 return 0; 333 } 334 335 ha->type = GDT_PCI; 336 ha->ic_all_size = sizeof(dp6_ptr->u); 337 338 /* special command to controller BIOS */ 339 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); 340 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); 341 gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); 342 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); 343 gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); 344 gdth_writeb(0, &dp6_ptr->io.event); 345 retries = INIT_RETRIES; 346 gdth_delay(20); 347 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { 348 if (--retries == 0) { 349 printk("initialization error\n"); 350 gdth_munmap(ha->brd); 351 return 0; 352 } 353 gdth_delay(1); 354 } 355 gdth_writeb(0, &dp6_ptr->u.ic.S_Status); 356 gdth_writeb(0xff, &dp6_ptr->io.irqdel); 357 #endif 358 359 gdt->sc_ic_all_size = GDT_DPRAM_SZ; 360 361 gdt->sc_copy_cmd = gdt_pci_copy_cmd; 362 gdt->sc_get_status = gdt_pci_get_status; 363 gdt->sc_intr = gdt_pci_intr; 364 gdt->sc_release_event = gdt_pci_release_event; 365 gdt->sc_set_sema0 = gdt_pci_set_sema0; 366 gdt->sc_test_busy = gdt_pci_test_busy; 367 368 break; 369 370 case GDT_PCINEW: 371 bus_space_set_region_4(dpmemt, dpmemh, 0, 0, 372 GDT_DPR_IF_SZ >> 2); 373 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { 374 printf("cannot write to DPMEM\n"); 375 goto bail_out; 376 } 377 378 #if 0 379 /* disable board interrupts, deinit services */ 380 outb(0x00,PTR2USHORT(&ha->plx->control1)); 381 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); 382 383 gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); 384 gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); 385 386 gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); 387 gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); 388 389 outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); 390 391 retries = INIT_RETRIES; 392 gdth_delay(20); 393 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { 394 if (--retries == 0) { 395 printk("initialization error (DEINIT failed)\n"); 396 gdth_munmap(ha->brd); 397 return 0; 398 } 399 gdth_delay(1); 400 } 401 prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); 402 gdth_writeb(0, &dp6c_ptr->u.ic.Status); 403 if (prot_ver != PROTOCOL_VERSION) { 404 printk("illegal protocol version\n"); 405 gdth_munmap(ha->brd); 406 return 0; 407 } 408 409 ha->type = GDT_PCINEW; 410 ha->ic_all_size = sizeof(dp6c_ptr->u); 411 412 /* special command to controller BIOS */ 413 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); 414 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); 415 gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); 416 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); 417 gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); 418 419 outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); 420 421 retries = INIT_RETRIES; 422 gdth_delay(20); 423 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { 424 if (--retries == 0) { 425 printk("initialization error\n"); 426 gdth_munmap(ha->brd); 427 return 0; 428 } 429 gdth_delay(1); 430 } 431 gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); 432 #endif 433 434 gdt->sc_ic_all_size = GDT_PCINEW_SZ; 435 436 gdt->sc_copy_cmd = gdt_pcinew_copy_cmd; 437 gdt->sc_get_status = gdt_pcinew_get_status; 438 gdt->sc_intr = gdt_pcinew_intr; 439 gdt->sc_release_event = gdt_pcinew_release_event; 440 gdt->sc_set_sema0 = gdt_pcinew_set_sema0; 441 gdt->sc_test_busy = gdt_pcinew_test_busy; 442 443 break; 444 445 case GDT_MPR: 446 bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC, GDT_MPR_MAGIC); 447 if (bus_space_read_4(dpmemt, dpmemh, GDT_MPR_IC) != 448 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, 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 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 (status 0x%x)\n", 485 bus_space_read_1(dpmemt, dpmemh, 486 GDT_MPR_IC + GDT_S_STATUS)); 487 goto bail_out; 488 } 489 DELAY(1); 490 } 491 492 protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh, 493 GDT_MPR_IC + GDT_S_INFO); 494 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 495 0); 496 if (protocol != GDT_PROTOCOL_VERSION) { 497 printf("unsupported protocol %d\n", protocol); 498 goto bail_out; 499 } 500 501 /* special commnd to controller BIOS */ 502 bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO, 0); 503 bus_space_write_4(dpmemt, dpmemh, 504 GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), 0); 505 bus_space_write_4(dpmemt, dpmemh, 506 GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), 1); 507 bus_space_write_4(dpmemt, dpmemh, 508 GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), 0); 509 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 510 0xfe); 511 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_LDOOR, 1); 512 513 DELAY(20); 514 retries = GDT_RETRIES; 515 while (bus_space_read_1(dpmemt, dpmemh, 516 GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { 517 if (--retries == 0) { 518 printf("initialization error\n"); 519 goto bail_out; 520 } 521 DELAY(1); 522 } 523 524 bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 525 0); 526 527 gdt->sc_ic_all_size = GDT_MPR_SZ; 528 529 gdt->sc_copy_cmd = gdt_mpr_copy_cmd; 530 gdt->sc_get_status = gdt_mpr_get_status; 531 gdt->sc_intr = gdt_mpr_intr; 532 gdt->sc_release_event = gdt_mpr_release_event; 533 gdt->sc_set_sema0 = gdt_mpr_set_sema0; 534 gdt->sc_test_busy = gdt_mpr_test_busy; 535 } 536 537 if (pci_intr_map(pa, &ih)) { 538 printf("couldn't map interrupt\n"); 539 goto bail_out; 540 } 541 intrstr = pci_intr_string(pa->pa_pc, ih); 542 gdt->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, gdt_intr, gdt, 543 gdt->sc_dev.dv_xname); 544 if (gdt->sc_ih == NULL) { 545 printf("couldn't establish interrupt"); 546 if (intrstr != NULL) 547 printf(" at %s", intrstr); 548 printf("\n"); 549 goto bail_out; 550 } 551 status |= INTR_ESTABLISHED; 552 if (intrstr != NULL) 553 printf("%s ", intrstr); 554 555 if (gdt_attach(gdt)) 556 goto bail_out; 557 558 gdt_pci_enable_intr(gdt); 559 560 return; 561 562 bail_out: 563 if (status & DPMEM_MAPPED) 564 bus_space_unmap(dpmemt, dpmemh, dpmemsize); 565 if (status & IOMEM_MAPPED) 566 bus_space_unmap(iomemt, iomemh, iomembase); 567 if (status & IO_MAPPED) 568 bus_space_unmap(iot, ioh, iosize); 569 if (status & INTR_ESTABLISHED) 570 pci_intr_disestablish(pa->pa_pc, gdt->sc_ih); 571 return; 572 } 573 574 /* Enable interrupts */ 575 void 576 gdt_pci_enable_intr(gdt) 577 struct gdt_softc *gdt; 578 { 579 GDT_DPRINTF(GDT_D_INTR, ("gdt_pci_enable_intr(%p) ", gdt)); 580 581 switch(GDT_CLASS(gdt)) { 582 case GDT_PCI: 583 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_IRQDEL, 584 1); 585 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 586 GDT_CMD_INDEX, 0); 587 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_IRQEN, 588 1); 589 break; 590 591 case GDT_PCINEW: 592 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_EDOOR_REG, 593 0xff); 594 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_CONTROL1, 3); 595 break; 596 597 case GDT_MPR: 598 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 599 GDT_MPR_EDOOR, 0xff); 600 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, 601 bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 602 GDT_EDOOR_EN) & ~4); 603 break; 604 } 605 } 606 607 /* 608 * "old" PCI controller-specific functions 609 */ 610 611 void 612 gdt_pci_copy_cmd(gdt, ccb) 613 struct gdt_softc *gdt; 614 struct gdt_ccb *ccb; 615 { 616 /* XXX Not yet implemented */ 617 } 618 619 u_int8_t 620 gdt_pci_get_status(gdt) 621 struct gdt_softc *gdt; 622 { 623 /* XXX Not yet implemented */ 624 return (0); 625 } 626 627 void 628 gdt_pci_intr(gdt, ctx) 629 struct gdt_softc *gdt; 630 struct gdt_intr_ctx *ctx; 631 { 632 /* XXX Not yet implemented */ 633 } 634 635 void 636 gdt_pci_release_event(gdt, ccb) 637 struct gdt_softc *gdt; 638 struct gdt_ccb *ccb; 639 { 640 /* XXX Not yet implemented */ 641 } 642 643 void 644 gdt_pci_set_sema0(gdt) 645 struct gdt_softc *gdt; 646 { 647 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_SEMA0, 1); 648 } 649 650 int 651 gdt_pci_test_busy(gdt) 652 struct gdt_softc *gdt; 653 { 654 /* XXX Not yet implemented */ 655 return (0); 656 } 657 658 /* 659 * "new" PCI controller-specific functions 660 */ 661 662 void 663 gdt_pcinew_copy_cmd(gdt, ccb) 664 struct gdt_softc *gdt; 665 struct gdt_ccb *ccb; 666 { 667 /* XXX Not yet implemented */ 668 } 669 670 u_int8_t 671 gdt_pcinew_get_status(gdt) 672 struct gdt_softc *gdt; 673 { 674 /* XXX Not yet implemented */ 675 return (0); 676 } 677 678 void 679 gdt_pcinew_intr(gdt, ctx) 680 struct gdt_softc *gdt; 681 struct gdt_intr_ctx *ctx; 682 { 683 /* XXX Not yet implemented */ 684 } 685 686 void 687 gdt_pcinew_release_event(gdt, ccb) 688 struct gdt_softc *gdt; 689 struct gdt_ccb *ccb; 690 { 691 /* XXX Not yet implemented */ 692 } 693 694 void 695 gdt_pcinew_set_sema0(gdt) 696 struct gdt_softc *gdt; 697 { 698 bus_space_write_1(gdt->sc_iot, gdt->sc_ioh, GDT_SEMA0_REG, 1); 699 } 700 701 int 702 gdt_pcinew_test_busy(gdt) 703 struct gdt_softc *gdt; 704 { 705 /* XXX Not yet implemented */ 706 return (0); 707 } 708 709 /* 710 * MPR PCI controller-specific functions 711 */ 712 713 void 714 gdt_mpr_copy_cmd(gdt, ccb) 715 struct gdt_softc *gdt; 716 struct gdt_ccb *ccb; 717 { 718 u_int16_t cp_count = roundup(gdt->sc_cmd_len, sizeof (u_int32_t)); 719 u_int16_t dp_offset = gdt->sc_cmd_off; 720 u_int16_t cmd_no = gdt->sc_cmd_cnt++; 721 722 GDT_DPRINTF(GDT_D_CMD, ("gdt_mpr_copy_cmd(%p) ", gdt)); 723 724 gdt->sc_cmd_off += cp_count; 725 726 bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, 727 GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET, 728 GDT_DPMEM_COMMAND_OFFSET + dp_offset); 729 bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, 730 GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID, 731 ccb->gc_service); 732 bus_space_write_raw_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, 733 GDT_MPR_IC + GDT_DPR_CMD + dp_offset, gdt->sc_cmd, cp_count); 734 } 735 736 u_int8_t 737 gdt_mpr_get_status(gdt) 738 struct gdt_softc *gdt; 739 { 740 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_get_status(%p) ", gdt)); 741 742 return bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR); 743 } 744 745 void 746 gdt_mpr_intr(gdt, ctx) 747 struct gdt_softc *gdt; 748 struct gdt_intr_ctx *ctx; 749 { 750 GDT_DPRINTF(GDT_D_INTR, ("gdt_mpr_intr(%p) ", gdt)); 751 752 if (ctx->istatus & 0x80) { /* error flag */ 753 ctx->istatus &= ~0x80; 754 ctx->cmd_status = bus_space_read_2(gdt->sc_dpmemt, 755 gdt->sc_dpmemh, GDT_MPR_STATUS); 756 if (ctx->istatus == GDT_ASYNCINDEX) { 757 ctx->service = bus_space_read_2(gdt->sc_dpmemt, 758 gdt->sc_dpmemh, GDT_MPR_SERVICE); 759 ctx->info2 = bus_space_read_4(gdt->sc_dpmemt, 760 gdt->sc_dpmemh, GDT_MPR_INFO + sizeof (u_int32_t)); 761 } 762 } else /* no error */ 763 ctx->cmd_status = GDT_S_OK; 764 765 ctx->info = 766 bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_INFO); 767 768 if (gdt_polling) /* init. -> more info */ 769 ctx->info2 = bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, 770 GDT_MPR_INFO + sizeof (u_int32_t)); 771 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); 772 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA1, 0); 773 } 774 775 void 776 gdt_mpr_release_event(gdt, ccb) 777 struct gdt_softc *gdt; 778 struct gdt_ccb *ccb; 779 { 780 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_release_event(%p) ", gdt)); 781 782 if (gdt_dec16(gdt->sc_cmd + GDT_CMD_OPCODE) == GDT_INIT) 783 ccb->gc_service |= 0x80; 784 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); 785 } 786 787 void 788 gdt_mpr_set_sema0(gdt) 789 struct gdt_softc *gdt; 790 { 791 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_set_sema0(%p) ", gdt)); 792 793 bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA0, 1); 794 } 795 796 int 797 gdt_mpr_test_busy(gdt) 798 struct gdt_softc *gdt; 799 { 800 GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_test_busy(%p) ", gdt)); 801 802 return (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 803 GDT_MPR_SEMA0) & 1); 804 } 805