1 /* $FreeBSD$ */ 2 /* $Id: isp_pci.c,v 1.4 1998/09/15 10:06:22 gibbs Exp $ */ 3 /* 4 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 5 * FreeBSD Version. 6 * 7 *--------------------------------------- 8 * Copyright (c) 1997, 1998 by Matthew Jacob 9 * NASA/Ames Research Center 10 * All rights reserved. 11 *--------------------------------------- 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice immediately at the beginning of the file, without modification, 18 * this list of conditions, and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. The name of the author may not be used to endorse or promote products 23 * derived from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 #include <dev/isp/isp_freebsd.h> 38 #include <dev/isp/asm_pci.h> 39 #include <sys/malloc.h> 40 #include <vm/vm.h> 41 #include <vm/pmap.h> 42 #include <vm/vm_extern.h> 43 44 45 #include <pci/pcireg.h> 46 #include <pci/pcivar.h> 47 48 #ifdef SCSI_CAM 49 #include <machine/bus_memio.h> 50 #include <machine/bus_pio.h> 51 #include <machine/bus.h> 52 #endif 53 54 static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 55 static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 56 static int isp_pci_mbxdma __P((struct ispsoftc *)); 57 static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 58 ispreq_t *, u_int8_t *, u_int8_t)); 59 #ifdef SCSI_CAM 60 static void 61 isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 62 #else 63 #define isp_pci_dmateardown NULL 64 #endif 65 66 static void isp_pci_reset1 __P((struct ispsoftc *)); 67 static void isp_pci_dumpregs __P((struct ispsoftc *)); 68 69 static struct ispmdvec mdvec = { 70 isp_pci_rd_reg, 71 isp_pci_wr_reg, 72 isp_pci_mbxdma, 73 isp_pci_dmasetup, 74 isp_pci_dmateardown, 75 NULL, 76 isp_pci_reset1, 77 isp_pci_dumpregs, 78 ISP_RISC_CODE, 79 ISP_CODE_LENGTH, 80 ISP_CODE_ORG, 81 ISP_CODE_VERSION, 82 BIU_BURST_ENABLE, 83 0 84 }; 85 86 static struct ispmdvec mdvec_2100 = { 87 isp_pci_rd_reg, 88 isp_pci_wr_reg, 89 isp_pci_mbxdma, 90 isp_pci_dmasetup, 91 isp_pci_dmateardown, 92 NULL, 93 isp_pci_reset1, 94 isp_pci_dumpregs, 95 ISP2100_RISC_CODE, 96 ISP2100_CODE_LENGTH, 97 ISP2100_CODE_ORG, 98 ISP2100_CODE_VERSION, 99 BIU_BURST_ENABLE, 100 0 101 }; 102 103 #ifndef PCIM_CMD_INVEN 104 #define PCIM_CMD_INVEN 0x10 105 #endif 106 #ifndef PCIM_CMD_BUSMASTEREN 107 #define PCIM_CMD_BUSMASTEREN 0x0004 108 #endif 109 110 #ifndef PCI_VENDOR_QLOGIC 111 #define PCI_VENDOR_QLOGIC 0x1077 112 #endif 113 114 #ifndef PCI_PRODUCT_QLOGIC_ISP1020 115 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 116 #endif 117 118 #define PCI_QLOGIC_ISP \ 119 ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 120 121 #ifndef PCI_PRODUCT_QLOGIC_ISP2100 122 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 123 #endif 124 125 #define PCI_QLOGIC_ISP2100 \ 126 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 127 128 #define IO_MAP_REG 0x10 129 #define MEM_MAP_REG 0x14 130 131 132 static char *isp_pci_probe __P((pcici_t tag, pcidi_t type)); 133 static void isp_pci_attach __P((pcici_t config_d, int unit)); 134 135 /* This distinguishing define is not right, but it does work */ 136 137 #ifndef SCSI_CAM 138 #define IO_SPACE_MAPPING 0 139 #define MEM_SPACE_MAPPING 1 140 typedef int bus_space_tag_t; 141 typedef u_long bus_space_handle_t; 142 #ifdef __alpha__ 143 #define bus_space_read_2(st, sh, offset) \ 144 (st == IO_SPACE_MAPPING)? \ 145 inw((pci_port_t)sh + offset) : readw((pci_port_t)sh + offset) 146 #define bus_space_write_2(st, sh, offset, val) \ 147 if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \ 148 writew((pci_port_t)sh + offset, val) 149 #else 150 #define bus_space_read_2(st, sh, offset) \ 151 (st == IO_SPACE_MAPPING)? \ 152 inw((pci_port_t)sh + offset) : *((u_int16_t *)(uintptr_t)sh) 153 #define bus_space_write_2(st, sh, offset, val) \ 154 if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \ 155 *((u_int16_t *)(uintptr_t)sh) = val 156 #endif 157 #else 158 #ifdef __alpha__ 159 #define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 160 #define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 161 #else 162 #define IO_SPACE_MAPPING I386_BUS_SPACE_IO 163 #define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 164 #endif 165 #endif 166 167 struct isp_pcisoftc { 168 struct ispsoftc pci_isp; 169 pcici_t pci_id; 170 bus_space_tag_t pci_st; 171 bus_space_handle_t pci_sh; 172 #ifdef SCSI_CAM 173 bus_dma_tag_t parent_dmat; 174 bus_dma_tag_t cntrol_dmat; 175 bus_dmamap_t cntrol_dmap; 176 bus_dmamap_t dmaps[MAXISPREQUEST]; 177 #endif 178 union { 179 sdparam _x; 180 struct { 181 fcparam _a; 182 char _b[ISP2100_SCRLEN]; 183 } _y; 184 } _z; 185 }; 186 187 static u_long ispunit; 188 189 struct pci_device isp_pci_driver = { 190 "isp", 191 isp_pci_probe, 192 isp_pci_attach, 193 &ispunit, 194 NULL 195 }; 196 DATA_SET (pcidevice_set, isp_pci_driver); 197 198 199 static char * 200 isp_pci_probe(tag, type) 201 pcici_t tag; 202 pcidi_t type; 203 { 204 static int oneshot = 1; 205 char *x; 206 207 switch (type) { 208 case PCI_QLOGIC_ISP: 209 x = "Qlogic ISP 10X0 PCI SCSI Adapter"; 210 break; 211 case PCI_QLOGIC_ISP2100: 212 x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 213 break; 214 default: 215 return (NULL); 216 } 217 if (oneshot) { 218 oneshot = 0; 219 printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 220 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 221 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 222 } 223 return (x); 224 } 225 226 227 static void 228 isp_pci_attach(config_id, unit) 229 pcici_t config_id; 230 int unit; 231 { 232 int mapped; 233 pci_port_t io_port; 234 u_int32_t data; 235 struct isp_pcisoftc *pcs; 236 struct ispsoftc *isp; 237 vm_offset_t vaddr, paddr; 238 ISP_LOCKVAL_DECL; 239 240 241 pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 242 if (pcs == NULL) { 243 printf("isp%d: cannot allocate softc\n", unit); 244 return; 245 } 246 bzero(pcs, sizeof (struct isp_pcisoftc)); 247 248 vaddr = paddr = NULL; 249 mapped = 0; 250 data = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); 251 if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 252 if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { 253 pcs->pci_st = MEM_SPACE_MAPPING; 254 pcs->pci_sh = vaddr; 255 mapped++; 256 } 257 } 258 if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 259 if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { 260 pcs->pci_st = IO_SPACE_MAPPING; 261 pcs->pci_sh = io_port; 262 mapped++; 263 } 264 } 265 if (mapped == 0) { 266 printf("isp%d: unable to map any ports!\n", unit); 267 free(pcs, M_DEVBUF); 268 return; 269 } 270 printf("isp%d: using %s space register mapping\n", unit, 271 pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 272 273 isp = &pcs->pci_isp; 274 (void) sprintf(isp->isp_name, "isp%d", unit); 275 isp->isp_osinfo.unit = unit; 276 277 data = pci_conf_read(config_id, PCI_ID_REG); 278 if (data == PCI_QLOGIC_ISP) { 279 isp->isp_mdvec = &mdvec; 280 isp->isp_type = ISP_HA_SCSI_UNKNOWN; 281 isp->isp_param = &pcs->_z._x; 282 } else if (data == PCI_QLOGIC_ISP2100) { 283 isp->isp_mdvec = &mdvec_2100; 284 isp->isp_type = ISP_HA_FC_2100; 285 isp->isp_param = &pcs->_z._y._a; 286 287 ISP_LOCK(isp); 288 data = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); 289 data |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 290 pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, data); 291 292 /* 293 * Wierd- we need to clear the lsb in offset 0x30 to take the 294 * chip out of reset state. 295 */ 296 data = pci_conf_read(config_id, 0x30); 297 data &= ~1; 298 pci_conf_write(config_id, 0x30, data); 299 ISP_UNLOCK(isp); 300 } else { 301 printf("%s: unknown dev (%x)- punting\n", isp->isp_name, data); 302 free(pcs, M_DEVBUF); 303 return; 304 } 305 306 #ifdef SCSI_CAM 307 if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT, 308 BUS_SPACE_MAXADDR, NULL, NULL, 1<<24, 309 255, 1<<24, 0, &pcs->parent_dmat) != 0) { 310 printf("%s: could not create master dma tag\n", isp->isp_name); 311 free(pcs, M_DEVBUF); 312 return; 313 } 314 #endif 315 if (pci_map_int(config_id, (void (*)(void *))isp_intr, 316 (void *)isp, &IMASK) == 0) { 317 printf("%s: could not map interrupt\n", isp->isp_name); 318 free(pcs, M_DEVBUF); 319 return; 320 } 321 322 pcs->pci_id = config_id; 323 ISP_LOCK(isp); 324 isp_reset(isp); 325 if (isp->isp_state != ISP_RESETSTATE) { 326 ISP_UNLOCK(isp); 327 free(pcs, M_DEVBUF); 328 return; 329 } 330 isp_init(isp); 331 if (isp->isp_state != ISP_INITSTATE) { 332 isp_uninit(isp); 333 ISP_UNLOCK(isp); 334 free(pcs, M_DEVBUF); 335 return; 336 } 337 isp_attach(isp); 338 if (isp->isp_state != ISP_RUNSTATE) { 339 isp_uninit(isp); 340 free(pcs, M_DEVBUF); 341 } 342 ISP_UNLOCK(isp); 343 } 344 345 #define PCI_BIU_REGS_OFF BIU_REGS_OFF 346 347 static u_int16_t 348 isp_pci_rd_reg(isp, regoff) 349 struct ispsoftc *isp; 350 int regoff; 351 { 352 u_int16_t rv; 353 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 354 int offset, oldsxp = 0; 355 356 if ((regoff & BIU_BLOCK) != 0) { 357 offset = PCI_BIU_REGS_OFF; 358 } else if ((regoff & MBOX_BLOCK) != 0) { 359 if (isp->isp_type & ISP_HA_SCSI) 360 offset = PCI_MBOX_REGS_OFF; 361 else 362 offset = PCI_MBOX_REGS2100_OFF; 363 } else if ((regoff & SXP_BLOCK) != 0) { 364 offset = PCI_SXP_REGS_OFF; 365 /* 366 * We will assume that someone has paused the RISC processor. 367 */ 368 oldsxp = isp_pci_rd_reg(isp, BIU_CONF1); 369 isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP); 370 } else { 371 offset = PCI_RISC_REGS_OFF; 372 } 373 regoff &= 0xff; 374 offset += regoff; 375 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 376 if ((regoff & SXP_BLOCK) != 0) { 377 isp_pci_wr_reg(isp, BIU_CONF1, oldsxp); 378 } 379 return (rv); 380 } 381 382 static void 383 isp_pci_wr_reg(isp, regoff, val) 384 struct ispsoftc *isp; 385 int regoff; 386 u_int16_t val; 387 { 388 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 389 int offset, oldsxp = 0; 390 if ((regoff & BIU_BLOCK) != 0) { 391 offset = PCI_BIU_REGS_OFF; 392 } else if ((regoff & MBOX_BLOCK) != 0) { 393 if (isp->isp_type & ISP_HA_SCSI) 394 offset = PCI_MBOX_REGS_OFF; 395 else 396 offset = PCI_MBOX_REGS2100_OFF; 397 } else if ((regoff & SXP_BLOCK) != 0) { 398 offset = PCI_SXP_REGS_OFF; 399 /* 400 * We will assume that someone has paused the RISC processor. 401 */ 402 oldsxp = isp_pci_rd_reg(isp, BIU_CONF1); 403 isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP); 404 } else { 405 offset = PCI_RISC_REGS_OFF; 406 } 407 regoff &= 0xff; 408 offset += regoff; 409 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 410 if ((regoff & SXP_BLOCK) != 0) { 411 isp_pci_wr_reg(isp, BIU_CONF1, oldsxp); 412 } 413 } 414 415 #ifdef SCSI_CAM 416 static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 417 static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 418 static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 419 420 static void 421 isp_map_rquest(arg, segs, nseg, error) 422 void *arg; 423 bus_dma_segment_t *segs; 424 int nseg; 425 int error; 426 { 427 struct ispsoftc *isp = (struct ispsoftc *) arg; 428 isp->isp_rquest_dma = segs->ds_addr; 429 } 430 431 static void 432 isp_map_result(arg, segs, nseg, error) 433 void *arg; 434 bus_dma_segment_t *segs; 435 int nseg; 436 int error; 437 { 438 struct ispsoftc *isp = (struct ispsoftc *) arg; 439 isp->isp_result_dma = segs->ds_addr; 440 } 441 442 static void 443 isp_map_fcscrt(arg, segs, nseg, error) 444 void *arg; 445 bus_dma_segment_t *segs; 446 int nseg; 447 int error; 448 { 449 struct ispsoftc *isp = (struct ispsoftc *) arg; 450 fcparam *fcp = isp->isp_param; 451 fcp->isp_scdma = segs->ds_addr; 452 } 453 454 static int 455 isp_pci_mbxdma(isp) 456 struct ispsoftc *isp; 457 { 458 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 459 caddr_t base; 460 u_int32_t len; 461 int i, error; 462 463 /* 464 * Allocate and map the request, result queues, plus FC scratch area. 465 */ 466 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 467 len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 468 if (isp->isp_type & ISP_HA_FC) { 469 len += ISP2100_SCRLEN; 470 } 471 if (bus_dma_tag_create(pci->parent_dmat, 0, 0, BUS_SPACE_MAXADDR, 472 BUS_SPACE_MAXADDR, NULL, NULL, len, 1, BUS_SPACE_MAXSIZE_32BIT, 473 0, &pci->cntrol_dmat) != 0) { 474 printf("%s: cannot create a dma tag for control spaces\n", 475 isp->isp_name); 476 return (1); 477 } 478 if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 479 BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 480 printf("%s: cannot allocate CCB memory\n", isp->isp_name); 481 return (1); 482 } 483 484 isp->isp_rquest = base; 485 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 486 ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, pci, 0); 487 488 isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 489 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 490 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, pci, 0); 491 492 if (isp->isp_type & ISP_HA_FC) { 493 fcparam *fcp = (fcparam *) isp->isp_param; 494 fcp->isp_scratch = isp->isp_result + 495 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 496 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 497 fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, pci, 0); 498 } 499 500 /* 501 * Use this opportunity to initialize/create data DMA maps. 502 */ 503 for (i = 0; i < MAXISPREQUEST; i++) { 504 error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 505 if (error) { 506 printf("%s: error %d creating data DMA maps\n", 507 isp->isp_name, error); 508 return (1); 509 } 510 } 511 return (0); 512 } 513 514 static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 515 typedef struct { 516 struct ispsoftc *isp; 517 ISP_SCSI_XFER_T *ccb; 518 ispreq_t *rq; 519 u_int8_t *iptrp; 520 u_int8_t optr; 521 u_int error; 522 } mush_t; 523 524 static void 525 dma2(arg, dm_segs, nseg, error) 526 void *arg; 527 bus_dma_segment_t *dm_segs; 528 int nseg; 529 int error; 530 { 531 mush_t *mp; 532 ISP_SCSI_XFER_T *ccb; 533 struct ispsoftc *isp; 534 struct isp_pcisoftc *pci; 535 bus_dmamap_t *dp; 536 bus_dma_segment_t *eseg; 537 ispreq_t *rq; 538 u_int8_t *iptrp; 539 u_int8_t optr; 540 ispcontreq_t *crq; 541 int drq, seglim, datalen; 542 543 mp = (mush_t *) arg; 544 if (error) { 545 mp->error = error; 546 return; 547 } 548 549 isp = mp->isp; 550 if (nseg < 1) { 551 printf("%s: zero or negative segment count\n", isp->isp_name); 552 mp->error = EFAULT; 553 return; 554 } 555 ccb = mp->ccb; 556 rq = mp->rq; 557 iptrp = mp->iptrp; 558 optr = mp->optr; 559 560 pci = (struct isp_pcisoftc *)isp; 561 dp = &pci->dmaps[rq->req_handle - 1]; 562 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 563 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 564 drq = REQFLAG_DATA_IN; 565 } else { 566 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 567 drq = REQFLAG_DATA_OUT; 568 } 569 570 datalen = XS_XFRLEN(ccb); 571 if (isp->isp_type & ISP_HA_FC) { 572 seglim = ISP_RQDSEG_T2; 573 ((ispreqt2_t *)rq)->req_totalcnt = datalen; 574 ((ispreqt2_t *)rq)->req_flags |= drq; 575 } else { 576 seglim = ISP_RQDSEG; 577 rq->req_flags |= drq; 578 } 579 580 eseg = dm_segs + nseg; 581 582 while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 583 if (isp->isp_type & ISP_HA_FC) { 584 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 585 rq2->req_dataseg[rq2->req_seg_count].ds_base = 586 dm_segs->ds_addr; 587 rq2->req_dataseg[rq2->req_seg_count].ds_count = 588 dm_segs->ds_len; 589 } else { 590 rq->req_dataseg[rq->req_seg_count].ds_base = 591 dm_segs->ds_addr; 592 rq->req_dataseg[rq->req_seg_count].ds_count = 593 dm_segs->ds_len; 594 } 595 datalen -= dm_segs->ds_len; 596 #if 0 597 if (isp->isp_type & ISP_HA_FC) { 598 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 599 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 600 isp->isp_name, rq->req_seg_count, 601 rq2->req_dataseg[rq2->req_seg_count].ds_count, 602 rq2->req_dataseg[rq2->req_seg_count].ds_base); 603 } else { 604 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 605 isp->isp_name, rq->req_seg_count, 606 rq->req_dataseg[rq->req_seg_count].ds_count, 607 rq->req_dataseg[rq->req_seg_count].ds_base); 608 } 609 #endif 610 rq->req_seg_count++; 611 dm_segs++; 612 } 613 614 if (datalen == 0) 615 return; 616 617 while (datalen > 0 && dm_segs != eseg) { 618 crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 619 *iptrp = (*iptrp + 1) & (RQUEST_QUEUE_LEN - 1); 620 if (*iptrp == optr) { 621 printf("%s: Request Queue Overflow+\n", isp->isp_name); 622 mp->error = EFBIG; 623 return; 624 } 625 rq->req_header.rqs_entry_count++; 626 bzero((void *)crq, sizeof (*crq)); 627 crq->req_header.rqs_entry_count = 1; 628 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 629 630 seglim = 0; 631 while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 632 crq->req_dataseg[seglim].ds_base = 633 dm_segs->ds_addr; 634 crq->req_dataseg[seglim].ds_count = 635 dm_segs->ds_len; 636 #if 0 637 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 638 isp->isp_name, rq->req_header.rqs_entry_count-1, 639 seglim, crq->req_dataseg[seglim].ds_count, 640 crq->req_dataseg[seglim].ds_base); 641 #endif 642 rq->req_seg_count++; 643 dm_segs++; 644 seglim++; 645 datalen -= dm_segs->ds_len; 646 } 647 } 648 } 649 650 static int 651 isp_pci_dmasetup(isp, ccb, rq, iptrp, optr) 652 struct ispsoftc *isp; 653 ISP_SCSI_XFER_T *ccb; 654 ispreq_t *rq; 655 u_int8_t *iptrp; 656 u_int8_t optr; 657 { 658 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 659 struct ccb_hdr *ccb_h; 660 struct ccb_scsiio *csio; 661 bus_dmamap_t *dp; 662 mush_t mush, *mp; 663 664 csio = (struct ccb_scsiio *) ccb; 665 ccb_h = &csio->ccb_h; 666 667 if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 668 rq->req_seg_count = 1; 669 return (0); 670 } 671 dp = &pci->dmaps[rq->req_handle - 1]; 672 673 /* 674 * Do a virtual grapevine step to collect info for 675 * a callback method we really didn't want. 676 */ 677 mp = &mush; 678 mp->isp = isp; 679 mp->ccb = ccb; 680 mp->rq = rq; 681 mp->iptrp = iptrp; 682 mp->optr = optr; 683 mp->error = 0; 684 685 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 686 if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 687 int error; 688 /* 689 * spls are spls, locks are locks. 690 * it isn't clear whether splsoftvm, if s spl, 691 * is a RAISE over splcam, or not. 692 */ 693 #if 0 694 int s; 695 s = splsoftvm(); 696 #endif 697 error = bus_dmamap_load(pci->parent_dmat, *dp, 698 csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 699 #if 0 700 splx(s); 701 #endif 702 if (error == EINPROGRESS) { 703 /* 704 * We simply aren't going to support 705 * this at this time. This mechanism 706 * is too rigid for my taste. 707 */ 708 printf("%s: sorry, we're not doing bounceio\n", 709 isp->isp_name); 710 bus_dmamap_unload(pci->parent_dmat, *dp); 711 mp->error = EINVAL; 712 } else if (error && mp->error == 0) { 713 mp->error = error; 714 } 715 } else { 716 /* Pointer to physical buffer */ 717 struct bus_dma_segment seg; 718 seg.ds_addr = (bus_addr_t)csio->data_ptr; 719 seg.ds_len = csio->dxfer_len; 720 dma2(mp, &seg, 1, 0); 721 } 722 } else { 723 struct bus_dma_segment *segs; 724 725 if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 726 printf("%s: Physical segment pointers unsupported", 727 isp->isp_name); 728 mp->error = EINVAL; 729 } else if ((ccb_h->flags&CAM_SG_LIST_PHYS) == 0) { 730 printf("%s: Virtual segment addresses unsupported", 731 isp->isp_name); 732 mp->error = EINVAL; 733 } else { 734 /* Just use the segments provided */ 735 segs = (struct bus_dma_segment *) csio->data_ptr; 736 dma2(mp, segs, csio->sglist_cnt, 0); 737 } 738 } 739 if (mp->error) { 740 if (mp->error != EFBIG) { 741 printf("%s: Unexepected error 0x%x returned from " 742 "bus_dmamap_load\n", isp->isp_name, mp->error); 743 ccb_h->status = CAM_REQ_TOO_BIG; 744 } else if (mp->error == EINVAL) { 745 ccb_h->status = CAM_REQ_INVALID; 746 } else { 747 ccb_h->status = CAM_UNREC_HBA_ERROR; 748 } 749 ccb_h->status |= CAM_DEV_QFRZN; 750 printf("%s:isp_pci_dmasetup->xpt_freeze_devq\n", isp->isp_name); 751 xpt_freeze_devq(ccb_h->path, 1); 752 } 753 return (mp->error); 754 } 755 756 static void 757 isp_pci_dmateardown(isp, ccb, handle) 758 struct ispsoftc *isp; 759 ISP_SCSI_XFER_T *ccb; 760 u_int32_t handle; 761 { 762 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 763 bus_dmamap_t *dp = &pci->dmaps[handle]; 764 765 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 766 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 767 } else { 768 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 769 } 770 bus_dmamap_unload(pci->parent_dmat, *dp); 771 } 772 773 #else /* SCSI_CAM */ 774 775 static int 776 isp_pci_mbxdma(isp) 777 struct ispsoftc *isp; 778 { 779 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 780 u_int32_t len; 781 int rseg; 782 783 /* XXXX CHECK FOR ALIGNMENT */ 784 /* 785 * Allocate and map the request queue. 786 */ 787 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 788 isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT); 789 if (isp->isp_rquest == NULL) { 790 printf("%s: cannot malloc request queue\n", isp->isp_name); 791 return (1); 792 } 793 isp->isp_rquest_dma = vtophys(isp->isp_rquest); 794 795 #if 0 796 printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma); 797 #endif 798 799 /* 800 * Allocate and map the result queue. 801 */ 802 len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 803 isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT); 804 if (isp->isp_result == NULL) { 805 free(isp->isp_rquest, M_DEVBUF); 806 printf("%s: cannot malloc result queue\n", isp->isp_name); 807 return (1); 808 } 809 isp->isp_result_dma = vtophys(isp->isp_result); 810 #if 0 811 printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma); 812 #endif 813 if (isp->isp_type & ISP_HA_FC) { 814 fcparam *fcp = isp->isp_param; 815 len = ISP2100_SCRLEN; 816 fcp->isp_scratch = (volatile caddr_t) &pci->_z._y._b; 817 fcp->isp_scdma = vtophys(fcp->isp_scratch); 818 } 819 return (0); 820 } 821 822 static int 823 isp_pci_dmasetup(isp, xs, rq, iptrp, optr) 824 struct ispsoftc *isp; 825 ISP_SCSI_XFER_T *xs; 826 ispreq_t *rq; 827 u_int8_t *iptrp; 828 u_int8_t optr; 829 { 830 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 831 ispcontreq_t *crq; 832 vm_offset_t vaddr; 833 int drq, seglim; 834 u_int32_t paddr, nextpaddr, datalen, size, *ctrp; 835 836 if (xs->datalen == 0) { 837 rq->req_seg_count = 1; 838 return (0); 839 } 840 841 if (xs->flags & SCSI_DATA_IN) { 842 drq = REQFLAG_DATA_IN; 843 } else { 844 drq = REQFLAG_DATA_OUT; 845 } 846 847 if (isp->isp_type & ISP_HA_FC) { 848 seglim = ISP_RQDSEG_T2; 849 ((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs); 850 ((ispreqt2_t *)rq)->req_flags |= drq; 851 } else { 852 seglim = ISP_RQDSEG; 853 rq->req_flags |= drq; 854 } 855 856 datalen = XS_XFRLEN(xs); 857 vaddr = (vm_offset_t) xs->data; 858 paddr = vtophys(vaddr); 859 860 while (datalen != 0 && rq->req_seg_count < seglim) { 861 if (isp->isp_type & ISP_HA_FC) { 862 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 863 rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr; 864 ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count; 865 } else { 866 rq->req_dataseg[rq->req_seg_count].ds_base = paddr; 867 ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count; 868 } 869 nextpaddr = paddr; 870 *(ctrp) = 0; 871 872 while (datalen != 0 && paddr == nextpaddr) { 873 nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 874 size = nextpaddr - paddr; 875 if (size > datalen) 876 size = datalen; 877 878 *(ctrp) += size; 879 vaddr += size; 880 datalen -= size; 881 if (datalen != 0) 882 paddr = vtophys(vaddr); 883 884 } 885 #if 0 886 if (isp->isp_type & ISP_HA_FC) { 887 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 888 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 889 isp->isp_name, rq->req_seg_count, 890 rq2->req_dataseg[rq2->req_seg_count].ds_count, 891 rq2->req_dataseg[rq2->req_seg_count].ds_base); 892 } else { 893 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 894 isp->isp_name, rq->req_seg_count, 895 rq->req_dataseg[rq->req_seg_count].ds_count, 896 rq->req_dataseg[rq->req_seg_count].ds_base); 897 } 898 #endif 899 rq->req_seg_count++; 900 } 901 902 903 904 if (datalen == 0) 905 return (0); 906 907 paddr = vtophys(vaddr); 908 while (datalen > 0) { 909 crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 910 *iptrp = (*iptrp + 1) & (RQUEST_QUEUE_LEN - 1); 911 if (*iptrp == optr) { 912 printf("%s: Request Queue Overflow\n", isp->isp_name); 913 XS_SETERR(xs, HBA_BOTCH); 914 return (EFBIG); 915 } 916 rq->req_header.rqs_entry_count++; 917 bzero((void *)crq, sizeof (*crq)); 918 crq->req_header.rqs_entry_count = 1; 919 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 920 921 for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) { 922 crq->req_dataseg[seglim].ds_base = paddr; 923 ctrp = &crq->req_dataseg[seglim].ds_count; 924 *(ctrp) = 0; 925 nextpaddr = paddr; 926 while (datalen != 0 && paddr == nextpaddr) { 927 nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 928 size = nextpaddr - paddr; 929 if (size > datalen) 930 size = datalen; 931 932 *(ctrp) += size; 933 vaddr += size; 934 datalen -= size; 935 if (datalen != 0) 936 paddr = vtophys(vaddr); 937 } 938 #if 0 939 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 940 isp->isp_name, rq->req_header.rqs_entry_count-1, 941 seglim, crq->req_dataseg[seglim].ds_count, 942 crq->req_dataseg[seglim].ds_base); 943 #endif 944 rq->req_seg_count++; 945 } 946 } 947 948 return (0); 949 } 950 #endif 951 952 static void 953 isp_pci_reset1(isp) 954 struct ispsoftc *isp; 955 { 956 /* Make sure the BIOS is disabled */ 957 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 958 } 959 960 static void 961 isp_pci_dumpregs(isp) 962 struct ispsoftc *isp; 963 { 964 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 965 printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 966 pci_conf_read(pci->pci_id, PCI_COMMAND_STATUS_REG)); 967 } 968