1 /* $NetBSD: isp_pci.c,v 1.36 1999/03/17 06:16:42 mjacob Exp $ */ 2 /* release_03_16_99 */ 3 /* 4 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 5 * 6 *--------------------------------------- 7 * Copyright (c) 1997, 1998 by Matthew Jacob 8 * NASA/Ames Research Center 9 * All rights reserved. 10 *--------------------------------------- 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice immediately at the beginning of the file, without modification, 17 * this list of conditions, and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 */ 37 38 #include <dev/ic/isp_netbsd.h> 39 #include <dev/microcode/isp/asm_pci.h> 40 41 #include <dev/pci/pcireg.h> 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcidevs.h> 44 45 static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 46 static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 47 #ifndef ISP_DISABLE_1080_SUPPORT 48 static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 49 static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 50 #endif 51 static int isp_pci_mbxdma __P((struct ispsoftc *)); 52 static int isp_pci_dmasetup __P((struct ispsoftc *, struct scsipi_xfer *, 53 ispreq_t *, u_int8_t *, u_int8_t)); 54 static void isp_pci_dmateardown __P((struct ispsoftc *, struct scsipi_xfer *, 55 u_int32_t)); 56 static void isp_pci_reset1 __P((struct ispsoftc *)); 57 static void isp_pci_dumpregs __P((struct ispsoftc *)); 58 static int isp_pci_intr __P((void *)); 59 60 #ifndef ISP_DISABLE_1020_SUPPORT 61 static struct ispmdvec mdvec = { 62 isp_pci_rd_reg, 63 isp_pci_wr_reg, 64 isp_pci_mbxdma, 65 isp_pci_dmasetup, 66 isp_pci_dmateardown, 67 NULL, 68 isp_pci_reset1, 69 isp_pci_dumpregs, 70 ISP_RISC_CODE, 71 ISP_CODE_LENGTH, 72 ISP_CODE_ORG, 73 ISP_CODE_VERSION, 74 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 75 0 76 }; 77 #endif 78 79 #ifndef ISP_DISABLE_1080_SUPPORT 80 static struct ispmdvec mdvec_1080 = { 81 isp_pci_rd_reg_1080, 82 isp_pci_wr_reg_1080, 83 isp_pci_mbxdma, 84 isp_pci_dmasetup, 85 isp_pci_dmateardown, 86 NULL, 87 isp_pci_reset1, 88 isp_pci_dumpregs, 89 0, 90 0, 91 0, 92 0, 93 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 94 0 95 }; 96 #endif 97 98 #ifndef ISP_DISABLE_2100_SUPPORT 99 static struct ispmdvec mdvec_2100 = { 100 isp_pci_rd_reg, 101 isp_pci_wr_reg, 102 isp_pci_mbxdma, 103 isp_pci_dmasetup, 104 isp_pci_dmateardown, 105 NULL, 106 isp_pci_reset1, 107 isp_pci_dumpregs, 108 ISP2100_RISC_CODE, 109 ISP2100_CODE_LENGTH, 110 ISP2100_CODE_ORG, 111 ISP2100_CODE_VERSION, 112 0, /* Irrelevant to the 2100 */ 113 0 114 }; 115 #endif 116 117 #ifndef PCI_VENDOR_QLOGIC 118 #define PCI_VENDOR_QLOGIC 0x1077 119 #endif 120 121 #ifndef PCI_PRODUCT_QLOGIC_ISP1020 122 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 123 #endif 124 125 #ifndef PCI_PRODUCT_QLOGIC_ISP1080 126 #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 127 #endif 128 129 #ifndef PCI_PRODUCT_QLOGIC_ISP1240 130 #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 131 #endif 132 133 #ifndef PCI_PRODUCT_QLOGIC_ISP2100 134 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 135 #endif 136 137 #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 138 139 #define PCI_QLOGIC_ISP1080 \ 140 ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 141 142 #define PCI_QLOGIC_ISP1240 \ 143 ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 144 145 #define PCI_QLOGIC_ISP2100 \ 146 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 147 148 #define IO_MAP_REG 0x10 149 #define MEM_MAP_REG 0x14 150 151 152 static int isp_pci_probe __P((struct device *, struct cfdata *, void *)); 153 static void isp_pci_attach __P((struct device *, struct device *, void *)); 154 155 struct isp_pcisoftc { 156 struct ispsoftc pci_isp; 157 pci_chipset_tag_t pci_pc; 158 pcitag_t pci_tag; 159 bus_space_tag_t pci_st; 160 bus_space_handle_t pci_sh; 161 bus_dma_tag_t pci_dmat; 162 bus_dmamap_t pci_scratch_dmap; /* for fcp only */ 163 bus_dmamap_t pci_rquest_dmap; 164 bus_dmamap_t pci_result_dmap; 165 bus_dmamap_t pci_xfer_dmap[MAXISPREQUEST]; 166 void * pci_ih; 167 int16_t pci_poff[_NREG_BLKS]; 168 }; 169 170 struct cfattach isp_pci_ca = { 171 sizeof (struct isp_pcisoftc), isp_pci_probe, isp_pci_attach 172 }; 173 174 static int 175 isp_pci_probe(parent, match, aux) 176 struct device *parent; 177 struct cfdata *match; 178 void *aux; 179 { 180 struct pci_attach_args *pa = aux; 181 switch (pa->pa_id) { 182 #ifndef ISP_DISABLE_1020_SUPPORT 183 case PCI_QLOGIC_ISP: 184 return (1); 185 #endif 186 #ifndef ISP_DISABLE_1080_SUPPORT 187 case PCI_QLOGIC_ISP1080: 188 #if 0 189 case PCI_QLOGIC_ISP1240: /* 1240 not ready yet */ 190 return (1); 191 #endif 192 #endif 193 #ifndef ISP_DISABLE_2100_SUPPORT 194 case PCI_QLOGIC_ISP2100: 195 return (1); 196 #endif 197 default: 198 return (0); 199 } 200 } 201 202 203 static void 204 isp_pci_attach(parent, self, aux) 205 struct device *parent, *self; 206 void *aux; 207 { 208 #ifdef DEBUG 209 static char oneshot = 1; 210 #endif 211 u_int32_t data; 212 struct pci_attach_args *pa = aux; 213 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) self; 214 struct ispsoftc *isp = &pcs->pci_isp; 215 bus_space_tag_t st, iot, memt; 216 bus_space_handle_t sh, ioh, memh; 217 pci_intr_handle_t ih; 218 const char *intrstr; 219 int ioh_valid, memh_valid, i; 220 ISP_LOCKVAL_DECL; 221 222 ioh_valid = (pci_mapreg_map(pa, IO_MAP_REG, 223 PCI_MAPREG_TYPE_IO, 0, 224 &iot, &ioh, NULL, NULL) == 0); 225 memh_valid = (pci_mapreg_map(pa, MEM_MAP_REG, 226 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, 227 &memt, &memh, NULL, NULL) == 0); 228 229 if (memh_valid) { 230 st = memt; 231 sh = memh; 232 } else if (ioh_valid) { 233 st = iot; 234 sh = ioh; 235 } else { 236 printf(": unable to map device registers\n"); 237 return; 238 } 239 printf("\n"); 240 241 pcs->pci_st = st; 242 pcs->pci_sh = sh; 243 pcs->pci_dmat = pa->pa_dmat; 244 pcs->pci_pc = pa->pa_pc; 245 pcs->pci_tag = pa->pa_tag; 246 pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 247 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 248 pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 249 pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 250 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 251 252 #ifndef ISP_DISABLE_1020_SUPPORT 253 if (pa->pa_id == PCI_QLOGIC_ISP) { 254 isp->isp_mdvec = &mdvec; 255 isp->isp_type = ISP_HA_SCSI_UNKNOWN; 256 isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT); 257 if (isp->isp_param == NULL) { 258 printf("%s: couldn't allocate sdparam table\n", 259 isp->isp_name); 260 return; 261 } 262 bzero(isp->isp_param, sizeof (sdparam)); 263 } 264 #endif 265 #ifndef ISP_DISABLE_1080_SUPPORT 266 if (pa->pa_id == PCI_QLOGIC_ISP1080) { 267 isp->isp_mdvec = &mdvec_1080; 268 isp->isp_type = ISP_HA_SCSI_1080; 269 isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT); 270 if (isp->isp_param == NULL) { 271 printf("%s: couldn't allocate sdparam table\n", 272 isp->isp_name); 273 return; 274 } 275 bzero(isp->isp_param, sizeof (sdparam)); 276 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 277 ISP1080_DMA_REGS_OFF; 278 } 279 #endif 280 #ifndef ISP_DISABLE_2100_SUPPORT 281 if (pa->pa_id == PCI_QLOGIC_ISP2100) { 282 isp->isp_mdvec = &mdvec_2100; 283 isp->isp_type = ISP_HA_FC_2100; 284 isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT); 285 if (isp->isp_param == NULL) { 286 printf("%s: couldn't allocate fcparam table\n", 287 isp->isp_name); 288 return; 289 } 290 bzero(isp->isp_param, sizeof (fcparam)); 291 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 292 PCI_MBOX_REGS2100_OFF; 293 } 294 #endif 295 296 /* 297 * Make sure that command register set sanely. 298 */ 299 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 300 data |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_INVALIDATE_ENABLE; 301 302 /* 303 * Not so sure about these- but I think it's important that they get 304 * enabled...... 305 */ 306 data |= PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 307 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, data); 308 309 /* 310 * Make sure that latency timer and cache line size is set sanely. 311 */ 312 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 313 data &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 314 data &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT); 315 data |= (0x40 << PCI_LATTIMER_SHIFT); 316 data |= (0x10 << PCI_CACHELINE_SHIFT); 317 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, data); 318 319 #ifdef DEBUG 320 if (oneshot) { 321 oneshot = 0; 322 printf("Qlogic ISP Driver, NetBSD (pci) Platform Version " 323 "%d.%d Core Version %d.%d\n", 324 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 325 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 326 } 327 #endif 328 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 329 pa->pa_intrline, &ih)) { 330 printf("%s: couldn't map interrupt\n", isp->isp_name); 331 free(isp->isp_param, M_DEVBUF); 332 return; 333 } 334 intrstr = pci_intr_string(pa->pa_pc, ih); 335 if (intrstr == NULL) 336 intrstr = "<I dunno>"; 337 pcs->pci_ih = 338 pci_intr_establish(pa->pa_pc, ih, IPL_BIO, isp_pci_intr, isp); 339 if (pcs->pci_ih == NULL) { 340 printf("%s: couldn't establish interrupt at %s\n", 341 isp->isp_name, intrstr); 342 free(isp->isp_param, M_DEVBUF); 343 return; 344 } 345 printf("%s: interrupting at %s\n", isp->isp_name, intrstr); 346 347 ISP_LOCK(isp); 348 isp_reset(isp); 349 if (isp->isp_state != ISP_RESETSTATE) { 350 ISP_UNLOCK(isp); 351 free(isp->isp_param, M_DEVBUF); 352 return; 353 } 354 isp_init(isp); 355 if (isp->isp_state != ISP_INITSTATE) { 356 isp_uninit(isp); 357 ISP_UNLOCK(isp); 358 free(isp->isp_param, M_DEVBUF); 359 return; 360 } 361 362 363 364 /* 365 * Create the DMA maps for the data transfers. 366 */ 367 for (i = 0; i < RQUEST_QUEUE_LEN; i++) { 368 if (bus_dmamap_create(pcs->pci_dmat, MAXPHYS, 369 (MAXPHYS / NBPG) + 1, MAXPHYS, 0, BUS_DMA_NOWAIT, 370 &pcs->pci_xfer_dmap[i])) { 371 printf("%s: can't create dma maps\n", 372 isp->isp_name); 373 isp_uninit(isp); 374 ISP_UNLOCK(isp); 375 return; 376 } 377 } 378 /* 379 * Do Generic attach now. 380 */ 381 isp_attach(isp); 382 if (isp->isp_state != ISP_RUNSTATE) { 383 isp_uninit(isp); 384 free(isp->isp_param, M_DEVBUF); 385 } 386 ISP_UNLOCK(isp); 387 } 388 389 static u_int16_t 390 isp_pci_rd_reg(isp, regoff) 391 struct ispsoftc *isp; 392 int regoff; 393 { 394 u_int16_t rv; 395 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 396 int offset, oldconf = 0; 397 398 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 399 /* 400 * We will assume that someone has paused the RISC processor. 401 */ 402 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 403 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 404 } 405 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 406 offset += (regoff & 0xff); 407 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 408 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 409 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 410 } 411 return (rv); 412 } 413 414 static void 415 isp_pci_wr_reg(isp, regoff, val) 416 struct ispsoftc *isp; 417 int regoff; 418 u_int16_t val; 419 { 420 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 421 int offset, oldconf = 0; 422 423 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 424 /* 425 * We will assume that someone has paused the RISC processor. 426 */ 427 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 428 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 429 } 430 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 431 offset += (regoff & 0xff); 432 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 433 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 434 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 435 } 436 } 437 438 #ifndef ISP_DISABLE_1080_SUPPORT 439 static u_int16_t 440 isp_pci_rd_reg_1080(isp, regoff) 441 struct ispsoftc *isp; 442 int regoff; 443 { 444 u_int16_t rv; 445 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 446 int offset, oc = 0; 447 448 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 449 /* 450 * We will assume that someone has paused the RISC processor. 451 */ 452 oc = isp_pci_rd_reg(isp, BIU_CONF1); 453 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 454 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 455 oc = isp_pci_rd_reg(isp, BIU_CONF1); 456 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 457 } 458 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 459 offset += (regoff & 0xff); 460 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 461 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 462 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 463 isp_pci_wr_reg(isp, BIU_CONF1, oc); 464 } 465 return (rv); 466 } 467 468 static void 469 isp_pci_wr_reg_1080(isp, regoff, val) 470 struct ispsoftc *isp; 471 int regoff; 472 u_int16_t val; 473 { 474 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 475 int offset, oc = 0; 476 477 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 478 /* 479 * We will assume that someone has paused the RISC processor. 480 */ 481 oc = isp_pci_rd_reg(isp, BIU_CONF1); 482 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 483 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 484 oc = isp_pci_rd_reg(isp, BIU_CONF1); 485 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 486 } 487 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 488 offset += (regoff & 0xff); 489 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 490 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 491 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 492 isp_pci_wr_reg(isp, BIU_CONF1, oc); 493 } 494 } 495 #endif 496 497 static int 498 isp_pci_mbxdma(isp) 499 struct ispsoftc *isp; 500 { 501 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 502 bus_dma_segment_t seg; 503 bus_size_t len; 504 fcparam *fcp; 505 int rseg; 506 507 /* 508 * Allocate and map the request queue. 509 */ 510 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 511 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg, 512 BUS_DMA_NOWAIT) || 513 bus_dmamem_map(pci->pci_dmat, &seg, rseg, len, 514 (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) 515 return (1); 516 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT, 517 &pci->pci_rquest_dmap) || 518 bus_dmamap_load(pci->pci_dmat, pci->pci_rquest_dmap, 519 (caddr_t)isp->isp_rquest, len, NULL, BUS_DMA_NOWAIT)) 520 return (1); 521 522 isp->isp_rquest_dma = pci->pci_rquest_dmap->dm_segs[0].ds_addr; 523 524 /* 525 * Allocate and map the result queue. 526 */ 527 len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 528 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg, 529 BUS_DMA_NOWAIT) || 530 bus_dmamem_map(pci->pci_dmat, &seg, rseg, len, 531 (caddr_t *)&isp->isp_result, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) 532 return (1); 533 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT, 534 &pci->pci_result_dmap) || 535 bus_dmamap_load(pci->pci_dmat, pci->pci_result_dmap, 536 (caddr_t)isp->isp_result, len, NULL, BUS_DMA_NOWAIT)) 537 return (1); 538 isp->isp_result_dma = pci->pci_result_dmap->dm_segs[0].ds_addr; 539 540 if (isp->isp_type & ISP_HA_SCSI) { 541 return (0); 542 } 543 544 fcp = isp->isp_param; 545 len = ISP2100_SCRLEN; 546 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg, 547 BUS_DMA_NOWAIT) || 548 bus_dmamem_map(pci->pci_dmat, &seg, rseg, len, 549 (caddr_t *)&fcp->isp_scratch, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) 550 return (1); 551 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT, 552 &pci->pci_scratch_dmap) || 553 bus_dmamap_load(pci->pci_dmat, pci->pci_scratch_dmap, 554 (caddr_t)fcp->isp_scratch, len, NULL, BUS_DMA_NOWAIT)) 555 return (1); 556 fcp->isp_scdma = pci->pci_scratch_dmap->dm_segs[0].ds_addr; 557 return (0); 558 } 559 560 static int 561 isp_pci_dmasetup(isp, xs, rq, iptrp, optr) 562 struct ispsoftc *isp; 563 struct scsipi_xfer *xs; 564 ispreq_t *rq; 565 u_int8_t *iptrp; 566 u_int8_t optr; 567 { 568 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 569 bus_dmamap_t dmap = pci->pci_xfer_dmap[rq->req_handle - 1]; 570 ispcontreq_t *crq; 571 int segcnt, seg, error, ovseg, seglim, drq; 572 573 if (xs->datalen == 0) { 574 rq->req_seg_count = 1; 575 goto mbxsync; 576 } 577 578 if (rq->req_handle > RQUEST_QUEUE_LEN || rq->req_handle < 1) { 579 panic("%s: bad handle (%d) in isp_pci_dmasetup\n", 580 isp->isp_name, rq->req_handle); 581 /* NOTREACHED */ 582 } 583 584 if (xs->flags & SCSI_DATA_IN) { 585 drq = REQFLAG_DATA_IN; 586 } else { 587 drq = REQFLAG_DATA_OUT; 588 } 589 590 if (isp->isp_type & ISP_HA_FC) { 591 seglim = ISP_RQDSEG_T2; 592 ((ispreqt2_t *)rq)->req_totalcnt = xs->datalen; 593 ((ispreqt2_t *)rq)->req_flags |= drq; 594 } else { 595 seglim = ISP_RQDSEG; 596 rq->req_flags |= drq; 597 } 598 error = bus_dmamap_load(pci->pci_dmat, dmap, xs->data, xs->datalen, 599 NULL, xs->flags & SCSI_NOSLEEP ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 600 if (error) { 601 XS_SETERR(xs, HBA_BOTCH); 602 return (CMD_COMPLETE); 603 } 604 605 segcnt = dmap->dm_nsegs; 606 607 for (seg = 0, rq->req_seg_count = 0; 608 seg < segcnt && rq->req_seg_count < seglim; 609 seg++, rq->req_seg_count++) { 610 if (isp->isp_type & ISP_HA_FC) { 611 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 612 rq2->req_dataseg[rq2->req_seg_count].ds_count = 613 dmap->dm_segs[seg].ds_len; 614 rq2->req_dataseg[rq2->req_seg_count].ds_base = 615 dmap->dm_segs[seg].ds_addr; 616 } else { 617 rq->req_dataseg[rq->req_seg_count].ds_count = 618 dmap->dm_segs[seg].ds_len; 619 rq->req_dataseg[rq->req_seg_count].ds_base = 620 dmap->dm_segs[seg].ds_addr; 621 } 622 } 623 624 if (seg == segcnt) 625 goto dmasync; 626 627 do { 628 crq = (ispcontreq_t *) 629 ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 630 *iptrp = (*iptrp + 1) & (RQUEST_QUEUE_LEN - 1); 631 if (*iptrp == optr) { 632 printf("%s: Request Queue Overflow++\n", 633 isp->isp_name); 634 bus_dmamap_unload(pci->pci_dmat, dmap); 635 XS_SETERR(xs, HBA_BOTCH); 636 return (CMD_COMPLETE); 637 } 638 rq->req_header.rqs_entry_count++; 639 bzero((void *)crq, sizeof (*crq)); 640 crq->req_header.rqs_entry_count = 1; 641 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 642 643 for (ovseg = 0; seg < segcnt && ovseg < ISP_CDSEG; 644 rq->req_seg_count++, seg++, ovseg++) { 645 crq->req_dataseg[ovseg].ds_count = 646 dmap->dm_segs[seg].ds_len; 647 crq->req_dataseg[ovseg].ds_base = 648 dmap->dm_segs[seg].ds_addr; 649 } 650 } while (seg < segcnt); 651 652 dmasync: 653 bus_dmamap_sync(pci->pci_dmat, dmap, 0, dmap->dm_mapsize, 654 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : 655 BUS_DMASYNC_PREWRITE); 656 657 mbxsync: 658 659 bus_dmamap_sync(pci->pci_dmat, pci->pci_rquest_dmap, 0, 660 pci->pci_rquest_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); 661 return (CMD_QUEUED); 662 } 663 664 static int 665 isp_pci_intr(arg) 666 void *arg; 667 { 668 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)arg; 669 bus_dmamap_sync(pci->pci_dmat, pci->pci_result_dmap, 0, 670 pci->pci_result_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD); 671 return (isp_intr(arg)); 672 } 673 674 static void 675 isp_pci_dmateardown(isp, xs, handle) 676 struct ispsoftc *isp; 677 struct scsipi_xfer *xs; 678 u_int32_t handle; 679 { 680 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 681 bus_dmamap_t dmap = pci->pci_xfer_dmap[handle]; 682 683 bus_dmamap_sync(pci->pci_dmat, dmap, 0, dmap->dm_mapsize, 684 xs->flags & SCSI_DATA_IN ? 685 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 686 bus_dmamap_unload(pci->pci_dmat, dmap); 687 } 688 689 static void 690 isp_pci_reset1(isp) 691 struct ispsoftc *isp; 692 { 693 /* Make sure the BIOS is disabled */ 694 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 695 } 696 697 static void 698 isp_pci_dumpregs(isp) 699 struct ispsoftc *isp; 700 { 701 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 702 printf("%s: PCI Status Command/Status=%x\n", pci->pci_isp.isp_name, 703 pci_conf_read(pci->pci_pc, pci->pci_tag, PCI_COMMAND_STATUS_REG)); 704 } 705