2/* 3 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 4 * FreeBSD Version. 5 * 6 *--------------------------------------- 7 * Copyright (c) 1997, 1998, 1999 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#include <dev/isp/isp_freebsd.h> 37#include <dev/isp/asm_pci.h> 38#include <sys/malloc.h> 39#include <vm/vm.h> 40#include <vm/pmap.h> 41#include <vm/vm_extern.h> 42 43 44#include <pci/pcireg.h> 45#include <pci/pcivar.h> 46 47#include <machine/bus_memio.h> 48#include <machine/bus_pio.h> 49#include <machine/bus.h> 50#include <machine/md_var.h> 51 52 53static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 54static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 55#ifndef ISP_DISABLE_1080_SUPPORT 56static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 57static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 58#endif 59static int isp_pci_mbxdma __P((struct ispsoftc *)); 60static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 61 ispreq_t *, u_int8_t *, u_int8_t)); 62static void 63isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 64 65static void isp_pci_reset1 __P((struct ispsoftc *)); 66static void isp_pci_dumpregs __P((struct ispsoftc *)); 67 68#ifndef ISP_DISABLE_1020_SUPPORT 69static 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|BIU_PCI_CONF1_FIFO_64, 83 0 84}; 85#endif 86 87#ifndef ISP_DISABLE_1080_SUPPORT 88static struct ispmdvec mdvec_1080 = { 89 isp_pci_rd_reg_1080, 90 isp_pci_wr_reg_1080, 91 isp_pci_mbxdma, 92 isp_pci_dmasetup, 93 isp_pci_dmateardown, 94 NULL, 95 isp_pci_reset1, 96 isp_pci_dumpregs, 97 ISP1080_RISC_CODE, 98 ISP1080_CODE_LENGTH, 99 ISP1080_CODE_ORG, 100 ISP1080_CODE_VERSION, 101 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 102 0 103}; 104#endif 105 106#ifndef ISP_DISABLE_2100_SUPPORT 107static struct ispmdvec mdvec_2100 = { 108 isp_pci_rd_reg, 109 isp_pci_wr_reg, 110 isp_pci_mbxdma, 111 isp_pci_dmasetup, 112 isp_pci_dmateardown, 113 NULL, 114 isp_pci_reset1, 115 isp_pci_dumpregs, 116 ISP2100_RISC_CODE, 117 ISP2100_CODE_LENGTH, 118 ISP2100_CODE_ORG, 119 ISP2100_CODE_VERSION, 120 0, /* Irrelevant to the 2100 */ 121 0 122}; 123#endif 124 125#ifndef ISP_DISABLE_2200_SUPPORT 126static struct ispmdvec mdvec_2200 = { 127 isp_pci_rd_reg, 128 isp_pci_wr_reg, 129 isp_pci_mbxdma, 130 isp_pci_dmasetup, 131 isp_pci_dmateardown, 132 NULL, 133 isp_pci_reset1, 134 isp_pci_dumpregs, 135 ISP2200_RISC_CODE, 136 ISP2200_CODE_LENGTH, 137 ISP2100_CODE_ORG, 138 ISP2200_CODE_VERSION, 139 0, 140 0 141}; 142#endif 143 144#ifndef SCSI_ISP_PREFER_MEM_MAP 145#define SCSI_ISP_PREFER_MEM_MAP 0 146#endif 147 148#ifndef PCIM_CMD_INVEN 149#define PCIM_CMD_INVEN 0x10 150#endif 151#ifndef PCIM_CMD_BUSMASTEREN 152#define PCIM_CMD_BUSMASTEREN 0x0004 153#endif 154#ifndef PCIM_CMD_PERRESPEN 155#define PCIM_CMD_PERRESPEN 0x0040 156#endif 157#ifndef PCIM_CMD_SEREN 158#define PCIM_CMD_SEREN 0x0100 159#endif 160 161#ifndef PCIR_COMMAND 162#define PCIR_COMMAND 0x04 163#endif 164 165#ifndef PCIR_CACHELNSZ 166#define PCIR_CACHELNSZ 0x0c 167#endif 168 169#ifndef PCIR_LATTIMER 170#define PCIR_LATTIMER 0x0d 171#endif 172 173#ifndef PCIR_ROMADDR 174#define PCIR_ROMADDR 0x30 175#endif 176 177#ifndef PCI_VENDOR_QLOGIC 178#define PCI_VENDOR_QLOGIC 0x1077 179#endif 180 181#ifndef PCI_PRODUCT_QLOGIC_ISP1020 182#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 183#endif 184 185#ifndef PCI_PRODUCT_QLOGIC_ISP1080 186#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 187#endif 188 189#ifndef PCI_PRODUCT_QLOGIC_ISP1240 190#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 191#endif 192 193#ifndef PCI_PRODUCT_QLOGIC_ISP2100 194#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 195#endif 196 197#ifndef PCI_PRODUCT_QLOGIC_ISP2200 198#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 199#endif 200 201#define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 202 203#define PCI_QLOGIC_ISP1080 \ 204 ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 205 206#define PCI_QLOGIC_ISP1240 \ 207 ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 208 209#define PCI_QLOGIC_ISP2100 \ 210 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 211 212#define PCI_QLOGIC_ISP2200 \ 213 ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 214 215#define IO_MAP_REG 0x10 216#define MEM_MAP_REG 0x14 217 218#define PCI_DFLT_LTNCY 0x40 219#define PCI_DFLT_LNSZ 0x10 220 221static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type)); 222static void isp_pci_attach __P((pcici_t config_d, int unit)); 223 224/* This distinguishing define is not right, but it does work */ 225#ifdef __alpha__ 226#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 227#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 228#else 229#define IO_SPACE_MAPPING I386_BUS_SPACE_IO 230#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 231#endif 232 233struct isp_pcisoftc { 234 struct ispsoftc pci_isp; 235 pcici_t pci_id; 236 bus_space_tag_t pci_st; 237 bus_space_handle_t pci_sh; 238 int16_t pci_poff[_NREG_BLKS]; 239 bus_dma_tag_t parent_dmat; 240 bus_dma_tag_t cntrol_dmat; 241 bus_dmamap_t cntrol_dmap; 242 bus_dmamap_t dmaps[MAXISPREQUEST]; 243}; 244 245static u_long ispunit; 246 247static struct pci_device isp_pci_driver = { 248 "isp", 249 isp_pci_probe, 250 isp_pci_attach, 251 &ispunit, 252 NULL 253}; 254COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver); 255 256 257static const char * 258isp_pci_probe(pcici_t tag, pcidi_t type) 259{ 260 static int oneshot = 1; 261 char *x; 262 263 switch (type) { 264#ifndef ISP_DISABLE_1020_SUPPORT 265 case PCI_QLOGIC_ISP: 266 x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 267 break; 268#endif 269#ifndef ISP_DISABLE_1080_SUPPORT 270 case PCI_QLOGIC_ISP1080: 271 x = "Qlogic ISP 1080 PCI SCSI Adapter"; 272 break; 273 case PCI_QLOGIC_ISP1240: 274 x = "Qlogic ISP 1240 PCI SCSI Adapter"; 275 break; 276#endif 277#ifndef ISP_DISABLE_2100_SUPPORT 278 case PCI_QLOGIC_ISP2100: 279 x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 280 break; 281#endif 282#ifndef ISP_DISABLE_2200_SUPPORT 283 case PCI_QLOGIC_ISP2200: 284 x = "Qlogic ISP 2200 PCI FC-AL Adapter"; 285 break; 286#endif 287 default: 288 return (NULL); 289 } 290 if (oneshot) { 291 oneshot = 0; 292 printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 293 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 294 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 295 } 296 return (x); 297} 298 299static void 300isp_pci_attach(pcici_t cfid, int unit) 301{ 302 int mapped, prefer_mem_map, bitmap; 303 pci_port_t io_port; 304 u_int32_t data, linesz, psize, basetype; 305 struct isp_pcisoftc *pcs; 306 struct ispsoftc *isp; 307 vm_offset_t vaddr, paddr; 308 struct ispmdvec *mdvp; 309 bus_size_t lim; 310 ISP_LOCKVAL_DECL; 311 312 pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 313 if (pcs == NULL) { 314 printf("isp%d: cannot allocate softc\n", unit); 315 return; 316 } 317 bzero(pcs, sizeof (struct isp_pcisoftc)); 318 319 /* 320 * Figure out if we're supposed to skip this one. 321 */ 322 if (getenv_int("isp_disable", &bitmap)) { 323 if (bitmap & (1 << unit)) { 324 printf("isp%d: not configuring\n", unit); 325 return; 326 } 327 } 328 329 /* 330 * Figure out which we should try first - memory mapping or i/o mapping? 331 */ 332#if SCSI_ISP_PREFER_MEM_MAP == 1 333 prefer_mem_map = 1; 334#else 335 prefer_mem_map = 0; 336#endif 337 bitmap = 0; 338 if (getenv_int("isp_mem_map", &bitmap)) { 339 if (bitmap & (1 << unit)) 340 prefer_mem_map = 1; 341 } 342 bitmap = 0; 343 if (getenv_int("isp_io_map", &bitmap)) { 344 if (bitmap & (1 << unit)) 345 prefer_mem_map = 0; 346 } 347 348 vaddr = paddr = NULL; 349 mapped = 0; 350 linesz = PCI_DFLT_LNSZ; 351 /* 352 * Note that pci_conf_read is a 32 bit word aligned function. 353 */ 354 data = pci_conf_read(cfid, PCIR_COMMAND); 355 if (prefer_mem_map) { 356 if (data & PCI_COMMAND_MEM_ENABLE) { 357 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 358 pcs->pci_st = MEM_SPACE_MAPPING; 359 pcs->pci_sh = vaddr; 360 mapped++; 361 } 362 } 363 if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 364 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 365 pcs->pci_st = IO_SPACE_MAPPING; 366 pcs->pci_sh = io_port; 367 mapped++; 368 } 369 } 370 } else { 371 if (data & PCI_COMMAND_IO_ENABLE) { 372 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 373 pcs->pci_st = IO_SPACE_MAPPING; 374 pcs->pci_sh = io_port; 375 mapped++; 376 } 377 } 378 if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 379 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 380 pcs->pci_st = MEM_SPACE_MAPPING; 381 pcs->pci_sh = vaddr; 382 mapped++; 383 } 384 } 385 } 386 if (mapped == 0) { 387 printf("isp%d: unable to map any ports!\n", unit); 388 free(pcs, M_DEVBUF); 389 return; 390 } 391 if (bootverbose) 392 printf("isp%d: using %s space register mapping\n", unit, 393 pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 394 395 data = pci_conf_read(cfid, PCI_ID_REG); 396 pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 397 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 398 pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 399 pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 400 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 401 /* 402 * GCC! 403 */ 404 mdvp = &mdvec; 405 basetype = ISP_HA_SCSI_UNKNOWN; 406 psize = sizeof (sdparam); 407 lim = BUS_SPACE_MAXSIZE_32BIT; 408#ifndef ISP_DISABLE_1020_SUPPORT 409 if (data == PCI_QLOGIC_ISP) { 410 mdvp = &mdvec; 411 basetype = ISP_HA_SCSI_UNKNOWN; 412 psize = sizeof (sdparam); 413 lim = BUS_SPACE_MAXSIZE_24BIT; 414 } 415#endif 416#ifndef ISP_DISABLE_1080_SUPPORT 417 if (data == PCI_QLOGIC_ISP1080) { 418 mdvp = &mdvec_1080; 419 basetype = ISP_HA_SCSI_1080; 420 psize = sizeof (sdparam); 421 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 422 ISP1080_DMA_REGS_OFF; 423 } 424 if (data == PCI_QLOGIC_ISP1240) { 425 mdvp = &mdvec_1080; 426 basetype = ISP_HA_SCSI_12X0; 427 psize = 2 * sizeof (sdparam); 428 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 429 ISP1080_DMA_REGS_OFF; 430 } 431#endif 432#ifndef ISP_DISABLE_2100_SUPPORT 433 if (data == PCI_QLOGIC_ISP2100) { 434 mdvp = &mdvec_2100; 435 basetype = ISP_HA_FC_2100; 436 psize = sizeof (fcparam); 437 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 438 PCI_MBOX_REGS2100_OFF; 439 data = pci_conf_read(cfid, PCI_CLASS_REG); 440 if ((data & 0xff) < 3) { 441 /* 442 * XXX: Need to get the actual revision 443 * XXX: number of the 2100 FB. At any rate, 444 * XXX: lower cache line size for early revision 445 * XXX; boards. 446 */ 447 linesz = 1; 448 } 449 } 450#endif 451#ifndef ISP_DISABLE_2200_SUPPORT 452 if (data == PCI_QLOGIC_ISP2200) { 453 mdvp = &mdvec_2200; 454 basetype = ISP_HA_FC_2200; 455 psize = sizeof (fcparam); 456 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 457 PCI_MBOX_REGS2100_OFF; 458 } 459#endif 460 isp = &pcs->pci_isp; 461 isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT); 462 if (isp->isp_param == NULL) { 463 printf("isp%d: cannot allocate parameter data\n", unit); 464 return; 465 } 466 bzero(isp->isp_param, psize); 467 isp->isp_mdvec = mdvp; 468 isp->isp_type = basetype; 469 (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 470 isp->isp_osinfo.unit = unit; 471 472 ISP_LOCK(isp); 473 474 /* 475 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 476 * are set. 477 */ 478 data = pci_cfgread(cfid, PCIR_COMMAND, 2); 479 data |= PCIM_CMD_SEREN | 480 PCIM_CMD_PERRESPEN | 481 PCIM_CMD_BUSMASTEREN | 482 PCIM_CMD_INVEN; 483 pci_cfgwrite(cfid, PCIR_COMMAND, 2, data); 484 485 /* 486 * Make sure the Cache Line Size register is set sensibly. 487 */ 488 data = pci_cfgread(cfid, PCIR_CACHELNSZ, 1); 489 if (data != linesz) { 490 data = PCI_DFLT_LNSZ; 491 printf("%s: set PCI line size to %d\n", isp->isp_name, data); 492 pci_cfgwrite(cfid, PCIR_CACHELNSZ, data, 1); 493 } 494 495 /* 496 * Make sure the Latency Timer is sane. 497 */ 498 data = pci_cfgread(cfid, PCIR_LATTIMER, 1); 499 if (data < PCI_DFLT_LTNCY) { 500 data = PCI_DFLT_LTNCY; 501 printf("%s: set PCI latency to %d\n", isp->isp_name, data); 502 pci_cfgwrite(cfid, PCIR_LATTIMER, data, 1); 503 } 504 505 /* 506 * Make sure we've disabled the ROM. 507 */ 508 data = pci_cfgread(cfid, PCIR_ROMADDR, 4); 509 data &= ~1; 510 pci_cfgwrite(cfid, PCIR_ROMADDR, data, 4); 511 ISP_UNLOCK(isp); 512 513 if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 514 BUS_SPACE_MAXADDR, NULL, NULL, lim + 1, 515 255, lim, 0, &pcs->parent_dmat) != 0) { 516 printf("%s: could not create master dma tag\n", isp->isp_name); 517 free(pcs, M_DEVBUF); 518 return; 519 } 520 if (pci_map_int(cfid, (void (*)(void *))isp_intr, 521 (void *)isp, &IMASK) == 0) { 522 printf("%s: could not map interrupt\n", isp->isp_name); 523 free(pcs, M_DEVBUF); 524 return; 525 } 526 527 pcs->pci_id = cfid; 528#ifdef SCSI_ISP_NO_FWLOAD_MASK 529 if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 530 isp->isp_confopts |= ISP_CFG_NORELOAD; 531#endif 532 if (getenv_int("isp_no_fwload", &bitmap)) { 533 if (bitmap & (1 << unit)) 534 isp->isp_confopts |= ISP_CFG_NORELOAD; 535 } 536 if (getenv_int("isp_fwload", &bitmap)) { 537 if (bitmap & (1 << unit)) 538 isp->isp_confopts &= ~ISP_CFG_NORELOAD; 539 } 540 541#ifdef SCSI_ISP_NO_NVRAM_MASK 542 if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 543 printf("%s: ignoring NVRAM\n", isp->isp_name); 544 isp->isp_confopts |= ISP_CFG_NONVRAM; 545 } 546#endif 547 if (getenv_int("isp_no_nvram", &bitmap)) { 548 if (bitmap & (1 << unit)) 549 isp->isp_confopts |= ISP_CFG_NONVRAM; 550 } 551 if (getenv_int("isp_nvram", &bitmap)) { 552 if (bitmap & (1 << unit)) 553 isp->isp_confopts &= ~ISP_CFG_NONVRAM; 554 } 555 556#ifdef SCSI_ISP_FCDUPLEX 557 if (IS_FC(isp)) { 558 if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) { 559 isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 560 } 561 } 562#endif 563 if (getenv_int("isp_fcduplex", &bitmap)) { 564 if (bitmap & (1 << unit)) 565 isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 566 } 567 if (getenv_int("isp_no_fcduplex", &bitmap)) { 568 if (bitmap & (1 << unit)) 569 isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX; 570 } 571 572 if (getenv_int("isp_seed", &isp->isp_osinfo.seed)) { 573 isp->isp_osinfo.seed <<= 8; 574 isp->isp_osinfo.seed += (unit + 1); 575 } else { 576 /* 577 * poor man's attempt at pseudo randomness. 578 */
| 2/* 3 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 4 * FreeBSD Version. 5 * 6 *--------------------------------------- 7 * Copyright (c) 1997, 1998, 1999 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#include <dev/isp/isp_freebsd.h> 37#include <dev/isp/asm_pci.h> 38#include <sys/malloc.h> 39#include <vm/vm.h> 40#include <vm/pmap.h> 41#include <vm/vm_extern.h> 42 43 44#include <pci/pcireg.h> 45#include <pci/pcivar.h> 46 47#include <machine/bus_memio.h> 48#include <machine/bus_pio.h> 49#include <machine/bus.h> 50#include <machine/md_var.h> 51 52 53static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 54static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 55#ifndef ISP_DISABLE_1080_SUPPORT 56static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 57static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 58#endif 59static int isp_pci_mbxdma __P((struct ispsoftc *)); 60static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 61 ispreq_t *, u_int8_t *, u_int8_t)); 62static void 63isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 64 65static void isp_pci_reset1 __P((struct ispsoftc *)); 66static void isp_pci_dumpregs __P((struct ispsoftc *)); 67 68#ifndef ISP_DISABLE_1020_SUPPORT 69static 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|BIU_PCI_CONF1_FIFO_64, 83 0 84}; 85#endif 86 87#ifndef ISP_DISABLE_1080_SUPPORT 88static struct ispmdvec mdvec_1080 = { 89 isp_pci_rd_reg_1080, 90 isp_pci_wr_reg_1080, 91 isp_pci_mbxdma, 92 isp_pci_dmasetup, 93 isp_pci_dmateardown, 94 NULL, 95 isp_pci_reset1, 96 isp_pci_dumpregs, 97 ISP1080_RISC_CODE, 98 ISP1080_CODE_LENGTH, 99 ISP1080_CODE_ORG, 100 ISP1080_CODE_VERSION, 101 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 102 0 103}; 104#endif 105 106#ifndef ISP_DISABLE_2100_SUPPORT 107static struct ispmdvec mdvec_2100 = { 108 isp_pci_rd_reg, 109 isp_pci_wr_reg, 110 isp_pci_mbxdma, 111 isp_pci_dmasetup, 112 isp_pci_dmateardown, 113 NULL, 114 isp_pci_reset1, 115 isp_pci_dumpregs, 116 ISP2100_RISC_CODE, 117 ISP2100_CODE_LENGTH, 118 ISP2100_CODE_ORG, 119 ISP2100_CODE_VERSION, 120 0, /* Irrelevant to the 2100 */ 121 0 122}; 123#endif 124 125#ifndef ISP_DISABLE_2200_SUPPORT 126static struct ispmdvec mdvec_2200 = { 127 isp_pci_rd_reg, 128 isp_pci_wr_reg, 129 isp_pci_mbxdma, 130 isp_pci_dmasetup, 131 isp_pci_dmateardown, 132 NULL, 133 isp_pci_reset1, 134 isp_pci_dumpregs, 135 ISP2200_RISC_CODE, 136 ISP2200_CODE_LENGTH, 137 ISP2100_CODE_ORG, 138 ISP2200_CODE_VERSION, 139 0, 140 0 141}; 142#endif 143 144#ifndef SCSI_ISP_PREFER_MEM_MAP 145#define SCSI_ISP_PREFER_MEM_MAP 0 146#endif 147 148#ifndef PCIM_CMD_INVEN 149#define PCIM_CMD_INVEN 0x10 150#endif 151#ifndef PCIM_CMD_BUSMASTEREN 152#define PCIM_CMD_BUSMASTEREN 0x0004 153#endif 154#ifndef PCIM_CMD_PERRESPEN 155#define PCIM_CMD_PERRESPEN 0x0040 156#endif 157#ifndef PCIM_CMD_SEREN 158#define PCIM_CMD_SEREN 0x0100 159#endif 160 161#ifndef PCIR_COMMAND 162#define PCIR_COMMAND 0x04 163#endif 164 165#ifndef PCIR_CACHELNSZ 166#define PCIR_CACHELNSZ 0x0c 167#endif 168 169#ifndef PCIR_LATTIMER 170#define PCIR_LATTIMER 0x0d 171#endif 172 173#ifndef PCIR_ROMADDR 174#define PCIR_ROMADDR 0x30 175#endif 176 177#ifndef PCI_VENDOR_QLOGIC 178#define PCI_VENDOR_QLOGIC 0x1077 179#endif 180 181#ifndef PCI_PRODUCT_QLOGIC_ISP1020 182#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 183#endif 184 185#ifndef PCI_PRODUCT_QLOGIC_ISP1080 186#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 187#endif 188 189#ifndef PCI_PRODUCT_QLOGIC_ISP1240 190#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 191#endif 192 193#ifndef PCI_PRODUCT_QLOGIC_ISP2100 194#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 195#endif 196 197#ifndef PCI_PRODUCT_QLOGIC_ISP2200 198#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 199#endif 200 201#define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 202 203#define PCI_QLOGIC_ISP1080 \ 204 ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 205 206#define PCI_QLOGIC_ISP1240 \ 207 ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 208 209#define PCI_QLOGIC_ISP2100 \ 210 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 211 212#define PCI_QLOGIC_ISP2200 \ 213 ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 214 215#define IO_MAP_REG 0x10 216#define MEM_MAP_REG 0x14 217 218#define PCI_DFLT_LTNCY 0x40 219#define PCI_DFLT_LNSZ 0x10 220 221static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type)); 222static void isp_pci_attach __P((pcici_t config_d, int unit)); 223 224/* This distinguishing define is not right, but it does work */ 225#ifdef __alpha__ 226#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 227#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 228#else 229#define IO_SPACE_MAPPING I386_BUS_SPACE_IO 230#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 231#endif 232 233struct isp_pcisoftc { 234 struct ispsoftc pci_isp; 235 pcici_t pci_id; 236 bus_space_tag_t pci_st; 237 bus_space_handle_t pci_sh; 238 int16_t pci_poff[_NREG_BLKS]; 239 bus_dma_tag_t parent_dmat; 240 bus_dma_tag_t cntrol_dmat; 241 bus_dmamap_t cntrol_dmap; 242 bus_dmamap_t dmaps[MAXISPREQUEST]; 243}; 244 245static u_long ispunit; 246 247static struct pci_device isp_pci_driver = { 248 "isp", 249 isp_pci_probe, 250 isp_pci_attach, 251 &ispunit, 252 NULL 253}; 254COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver); 255 256 257static const char * 258isp_pci_probe(pcici_t tag, pcidi_t type) 259{ 260 static int oneshot = 1; 261 char *x; 262 263 switch (type) { 264#ifndef ISP_DISABLE_1020_SUPPORT 265 case PCI_QLOGIC_ISP: 266 x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 267 break; 268#endif 269#ifndef ISP_DISABLE_1080_SUPPORT 270 case PCI_QLOGIC_ISP1080: 271 x = "Qlogic ISP 1080 PCI SCSI Adapter"; 272 break; 273 case PCI_QLOGIC_ISP1240: 274 x = "Qlogic ISP 1240 PCI SCSI Adapter"; 275 break; 276#endif 277#ifndef ISP_DISABLE_2100_SUPPORT 278 case PCI_QLOGIC_ISP2100: 279 x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 280 break; 281#endif 282#ifndef ISP_DISABLE_2200_SUPPORT 283 case PCI_QLOGIC_ISP2200: 284 x = "Qlogic ISP 2200 PCI FC-AL Adapter"; 285 break; 286#endif 287 default: 288 return (NULL); 289 } 290 if (oneshot) { 291 oneshot = 0; 292 printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 293 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 294 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 295 } 296 return (x); 297} 298 299static void 300isp_pci_attach(pcici_t cfid, int unit) 301{ 302 int mapped, prefer_mem_map, bitmap; 303 pci_port_t io_port; 304 u_int32_t data, linesz, psize, basetype; 305 struct isp_pcisoftc *pcs; 306 struct ispsoftc *isp; 307 vm_offset_t vaddr, paddr; 308 struct ispmdvec *mdvp; 309 bus_size_t lim; 310 ISP_LOCKVAL_DECL; 311 312 pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 313 if (pcs == NULL) { 314 printf("isp%d: cannot allocate softc\n", unit); 315 return; 316 } 317 bzero(pcs, sizeof (struct isp_pcisoftc)); 318 319 /* 320 * Figure out if we're supposed to skip this one. 321 */ 322 if (getenv_int("isp_disable", &bitmap)) { 323 if (bitmap & (1 << unit)) { 324 printf("isp%d: not configuring\n", unit); 325 return; 326 } 327 } 328 329 /* 330 * Figure out which we should try first - memory mapping or i/o mapping? 331 */ 332#if SCSI_ISP_PREFER_MEM_MAP == 1 333 prefer_mem_map = 1; 334#else 335 prefer_mem_map = 0; 336#endif 337 bitmap = 0; 338 if (getenv_int("isp_mem_map", &bitmap)) { 339 if (bitmap & (1 << unit)) 340 prefer_mem_map = 1; 341 } 342 bitmap = 0; 343 if (getenv_int("isp_io_map", &bitmap)) { 344 if (bitmap & (1 << unit)) 345 prefer_mem_map = 0; 346 } 347 348 vaddr = paddr = NULL; 349 mapped = 0; 350 linesz = PCI_DFLT_LNSZ; 351 /* 352 * Note that pci_conf_read is a 32 bit word aligned function. 353 */ 354 data = pci_conf_read(cfid, PCIR_COMMAND); 355 if (prefer_mem_map) { 356 if (data & PCI_COMMAND_MEM_ENABLE) { 357 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 358 pcs->pci_st = MEM_SPACE_MAPPING; 359 pcs->pci_sh = vaddr; 360 mapped++; 361 } 362 } 363 if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 364 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 365 pcs->pci_st = IO_SPACE_MAPPING; 366 pcs->pci_sh = io_port; 367 mapped++; 368 } 369 } 370 } else { 371 if (data & PCI_COMMAND_IO_ENABLE) { 372 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 373 pcs->pci_st = IO_SPACE_MAPPING; 374 pcs->pci_sh = io_port; 375 mapped++; 376 } 377 } 378 if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 379 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 380 pcs->pci_st = MEM_SPACE_MAPPING; 381 pcs->pci_sh = vaddr; 382 mapped++; 383 } 384 } 385 } 386 if (mapped == 0) { 387 printf("isp%d: unable to map any ports!\n", unit); 388 free(pcs, M_DEVBUF); 389 return; 390 } 391 if (bootverbose) 392 printf("isp%d: using %s space register mapping\n", unit, 393 pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 394 395 data = pci_conf_read(cfid, PCI_ID_REG); 396 pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 397 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 398 pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 399 pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 400 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 401 /* 402 * GCC! 403 */ 404 mdvp = &mdvec; 405 basetype = ISP_HA_SCSI_UNKNOWN; 406 psize = sizeof (sdparam); 407 lim = BUS_SPACE_MAXSIZE_32BIT; 408#ifndef ISP_DISABLE_1020_SUPPORT 409 if (data == PCI_QLOGIC_ISP) { 410 mdvp = &mdvec; 411 basetype = ISP_HA_SCSI_UNKNOWN; 412 psize = sizeof (sdparam); 413 lim = BUS_SPACE_MAXSIZE_24BIT; 414 } 415#endif 416#ifndef ISP_DISABLE_1080_SUPPORT 417 if (data == PCI_QLOGIC_ISP1080) { 418 mdvp = &mdvec_1080; 419 basetype = ISP_HA_SCSI_1080; 420 psize = sizeof (sdparam); 421 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 422 ISP1080_DMA_REGS_OFF; 423 } 424 if (data == PCI_QLOGIC_ISP1240) { 425 mdvp = &mdvec_1080; 426 basetype = ISP_HA_SCSI_12X0; 427 psize = 2 * sizeof (sdparam); 428 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 429 ISP1080_DMA_REGS_OFF; 430 } 431#endif 432#ifndef ISP_DISABLE_2100_SUPPORT 433 if (data == PCI_QLOGIC_ISP2100) { 434 mdvp = &mdvec_2100; 435 basetype = ISP_HA_FC_2100; 436 psize = sizeof (fcparam); 437 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 438 PCI_MBOX_REGS2100_OFF; 439 data = pci_conf_read(cfid, PCI_CLASS_REG); 440 if ((data & 0xff) < 3) { 441 /* 442 * XXX: Need to get the actual revision 443 * XXX: number of the 2100 FB. At any rate, 444 * XXX: lower cache line size for early revision 445 * XXX; boards. 446 */ 447 linesz = 1; 448 } 449 } 450#endif 451#ifndef ISP_DISABLE_2200_SUPPORT 452 if (data == PCI_QLOGIC_ISP2200) { 453 mdvp = &mdvec_2200; 454 basetype = ISP_HA_FC_2200; 455 psize = sizeof (fcparam); 456 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 457 PCI_MBOX_REGS2100_OFF; 458 } 459#endif 460 isp = &pcs->pci_isp; 461 isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT); 462 if (isp->isp_param == NULL) { 463 printf("isp%d: cannot allocate parameter data\n", unit); 464 return; 465 } 466 bzero(isp->isp_param, psize); 467 isp->isp_mdvec = mdvp; 468 isp->isp_type = basetype; 469 (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 470 isp->isp_osinfo.unit = unit; 471 472 ISP_LOCK(isp); 473 474 /* 475 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 476 * are set. 477 */ 478 data = pci_cfgread(cfid, PCIR_COMMAND, 2); 479 data |= PCIM_CMD_SEREN | 480 PCIM_CMD_PERRESPEN | 481 PCIM_CMD_BUSMASTEREN | 482 PCIM_CMD_INVEN; 483 pci_cfgwrite(cfid, PCIR_COMMAND, 2, data); 484 485 /* 486 * Make sure the Cache Line Size register is set sensibly. 487 */ 488 data = pci_cfgread(cfid, PCIR_CACHELNSZ, 1); 489 if (data != linesz) { 490 data = PCI_DFLT_LNSZ; 491 printf("%s: set PCI line size to %d\n", isp->isp_name, data); 492 pci_cfgwrite(cfid, PCIR_CACHELNSZ, data, 1); 493 } 494 495 /* 496 * Make sure the Latency Timer is sane. 497 */ 498 data = pci_cfgread(cfid, PCIR_LATTIMER, 1); 499 if (data < PCI_DFLT_LTNCY) { 500 data = PCI_DFLT_LTNCY; 501 printf("%s: set PCI latency to %d\n", isp->isp_name, data); 502 pci_cfgwrite(cfid, PCIR_LATTIMER, data, 1); 503 } 504 505 /* 506 * Make sure we've disabled the ROM. 507 */ 508 data = pci_cfgread(cfid, PCIR_ROMADDR, 4); 509 data &= ~1; 510 pci_cfgwrite(cfid, PCIR_ROMADDR, data, 4); 511 ISP_UNLOCK(isp); 512 513 if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 514 BUS_SPACE_MAXADDR, NULL, NULL, lim + 1, 515 255, lim, 0, &pcs->parent_dmat) != 0) { 516 printf("%s: could not create master dma tag\n", isp->isp_name); 517 free(pcs, M_DEVBUF); 518 return; 519 } 520 if (pci_map_int(cfid, (void (*)(void *))isp_intr, 521 (void *)isp, &IMASK) == 0) { 522 printf("%s: could not map interrupt\n", isp->isp_name); 523 free(pcs, M_DEVBUF); 524 return; 525 } 526 527 pcs->pci_id = cfid; 528#ifdef SCSI_ISP_NO_FWLOAD_MASK 529 if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 530 isp->isp_confopts |= ISP_CFG_NORELOAD; 531#endif 532 if (getenv_int("isp_no_fwload", &bitmap)) { 533 if (bitmap & (1 << unit)) 534 isp->isp_confopts |= ISP_CFG_NORELOAD; 535 } 536 if (getenv_int("isp_fwload", &bitmap)) { 537 if (bitmap & (1 << unit)) 538 isp->isp_confopts &= ~ISP_CFG_NORELOAD; 539 } 540 541#ifdef SCSI_ISP_NO_NVRAM_MASK 542 if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 543 printf("%s: ignoring NVRAM\n", isp->isp_name); 544 isp->isp_confopts |= ISP_CFG_NONVRAM; 545 } 546#endif 547 if (getenv_int("isp_no_nvram", &bitmap)) { 548 if (bitmap & (1 << unit)) 549 isp->isp_confopts |= ISP_CFG_NONVRAM; 550 } 551 if (getenv_int("isp_nvram", &bitmap)) { 552 if (bitmap & (1 << unit)) 553 isp->isp_confopts &= ~ISP_CFG_NONVRAM; 554 } 555 556#ifdef SCSI_ISP_FCDUPLEX 557 if (IS_FC(isp)) { 558 if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) { 559 isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 560 } 561 } 562#endif 563 if (getenv_int("isp_fcduplex", &bitmap)) { 564 if (bitmap & (1 << unit)) 565 isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 566 } 567 if (getenv_int("isp_no_fcduplex", &bitmap)) { 568 if (bitmap & (1 << unit)) 569 isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX; 570 } 571 572 if (getenv_int("isp_seed", &isp->isp_osinfo.seed)) { 573 isp->isp_osinfo.seed <<= 8; 574 isp->isp_osinfo.seed += (unit + 1); 575 } else { 576 /* 577 * poor man's attempt at pseudo randomness. 578 */
|
580 581 i >>= 5; 582 i &= 0x7; 583 584 /* 585 * This isn't very random, but it's the best we can do for 586 * the real edge case of cards that don't have WWNs. 587 */ 588 isp->isp_osinfo.seed += ((int) cfid->bus) << 16; 589 isp->isp_osinfo.seed += ((int) cfid->slot) << 8; 590 isp->isp_osinfo.seed += ((int) cfid->func); 591 while (version[i]) 592 isp->isp_osinfo.seed += (int) version[i++]; 593 isp->isp_osinfo.seed <<= 8; 594 isp->isp_osinfo.seed += (unit + 1); 595 } 596 597 ISP_LOCK(isp); 598 isp_reset(isp); 599 if (isp->isp_state != ISP_RESETSTATE) { 600 (void) pci_unmap_int(cfid); 601 ISP_UNLOCK(isp); 602 free(pcs, M_DEVBUF); 603 return; 604 } 605 isp_init(isp); 606 if (isp->isp_state != ISP_INITSTATE) { 607 /* If we're a Fibre Channel Card, we allow deferred attach */ 608 if (IS_SCSI(isp)) { 609 isp_uninit(isp); 610 (void) pci_unmap_int(cfid); /* Does nothing */ 611 ISP_UNLOCK(isp); 612 free(pcs, M_DEVBUF); 613 return; 614 } 615 } 616 isp_attach(isp); 617 if (isp->isp_state != ISP_RUNSTATE) { 618 /* If we're a Fibre Channel Card, we allow deferred attach */ 619 if (IS_SCSI(isp)) { 620 isp_uninit(isp); 621 (void) pci_unmap_int(cfid); /* Does nothing */ 622 ISP_UNLOCK(isp); 623 free(pcs, M_DEVBUF); 624 return; 625 } 626 } 627 ISP_UNLOCK(isp); 628#ifdef __alpha__ 629 /* 630 * THIS SHOULD NOT HAVE TO BE HERE 631 */ 632 alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim); 633#endif 634} 635 636static u_int16_t 637isp_pci_rd_reg(isp, regoff) 638 struct ispsoftc *isp; 639 int regoff; 640{ 641 u_int16_t rv; 642 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 643 int offset, oldconf = 0; 644 645 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 646 /* 647 * We will assume that someone has paused the RISC processor. 648 */ 649 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 650 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 651 } 652 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 653 offset += (regoff & 0xff); 654 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 655 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 656 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 657 } 658 return (rv); 659} 660 661static void 662isp_pci_wr_reg(isp, regoff, val) 663 struct ispsoftc *isp; 664 int regoff; 665 u_int16_t val; 666{ 667 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 668 int offset, oldconf = 0; 669 670 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 671 /* 672 * We will assume that someone has paused the RISC processor. 673 */ 674 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 675 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 676 } 677 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 678 offset += (regoff & 0xff); 679 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 680 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 681 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 682 } 683} 684 685#ifndef ISP_DISABLE_1080_SUPPORT 686static u_int16_t 687isp_pci_rd_reg_1080(isp, regoff) 688 struct ispsoftc *isp; 689 int regoff; 690{ 691 u_int16_t rv; 692 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 693 int offset, oc = 0; 694 695 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 696 /* 697 * We will assume that someone has paused the RISC processor. 698 */ 699 oc = isp_pci_rd_reg(isp, BIU_CONF1); 700 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 701 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 702 oc = isp_pci_rd_reg(isp, BIU_CONF1); 703 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 704 } 705 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 706 offset += (regoff & 0xff); 707 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 708 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 709 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 710 isp_pci_wr_reg(isp, BIU_CONF1, oc); 711 } 712 return (rv); 713} 714 715static void 716isp_pci_wr_reg_1080(isp, regoff, val) 717 struct ispsoftc *isp; 718 int regoff; 719 u_int16_t val; 720{ 721 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 722 int offset, oc = 0; 723 724 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 725 /* 726 * We will assume that someone has paused the RISC processor. 727 */ 728 oc = isp_pci_rd_reg(isp, BIU_CONF1); 729 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 730 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 731 oc = isp_pci_rd_reg(isp, BIU_CONF1); 732 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 733 } 734 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 735 offset += (regoff & 0xff); 736 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 737 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 738 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 739 isp_pci_wr_reg(isp, BIU_CONF1, oc); 740 } 741} 742#endif 743 744 745static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 746static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 747static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 748 749struct imush { 750 struct ispsoftc *isp; 751 int error; 752}; 753 754static void 755isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 756{ 757 struct imush *imushp = (struct imush *) arg; 758 if (error) { 759 imushp->error = error; 760 } else { 761 imushp->isp->isp_rquest_dma = segs->ds_addr; 762 } 763} 764 765static void 766isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 767{ 768 struct imush *imushp = (struct imush *) arg; 769 if (error) { 770 imushp->error = error; 771 } else { 772 imushp->isp->isp_result_dma = segs->ds_addr; 773 } 774} 775 776static void 777isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 778{ 779 struct imush *imushp = (struct imush *) arg; 780 if (error) { 781 imushp->error = error; 782 } else { 783 fcparam *fcp = imushp->isp->isp_param; 784 fcp->isp_scdma = segs->ds_addr; 785 } 786} 787 788static int 789isp_pci_mbxdma(struct ispsoftc *isp) 790{ 791 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 792 caddr_t base; 793 u_int32_t len; 794 int i, error; 795 bus_size_t lim; 796 struct imush im; 797 798 799 if (IS_FC(isp) || IS_1080(isp) || IS_12X0(isp)) 800 lim = BUS_SPACE_MAXADDR + 1; 801 else 802 lim = BUS_SPACE_MAXADDR_24BIT + 1; 803 804 /* 805 * Allocate and map the request, result queues, plus FC scratch area. 806 */ 807 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 808 len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 809 if (IS_FC(isp)) { 810 len += ISP2100_SCRLEN; 811 } 812 if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim, 813 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, 814 BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { 815 printf("%s: cannot create a dma tag for control spaces\n", 816 isp->isp_name); 817 return (1); 818 } 819 if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 820 BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 821 printf("%s: cannot allocate %d bytes of CCB memory\n", 822 isp->isp_name, len); 823 return (1); 824 } 825 826 isp->isp_rquest = base; 827 im.isp = isp; 828 im.error = 0; 829 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 830 ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, &im, 0); 831 if (im.error) { 832 printf("%s: error %d loading dma map for DMA request queue\n", 833 isp->isp_name, im.error); 834 return (1); 835 } 836 isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 837 im.error = 0; 838 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 839 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, &im, 0); 840 if (im.error) { 841 printf("%s: error %d loading dma map for DMA result queue\n", 842 isp->isp_name, im.error); 843 return (1); 844 } 845 846 /* 847 * Use this opportunity to initialize/create data DMA maps. 848 */ 849 for (i = 0; i < MAXISPREQUEST; i++) { 850 error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 851 if (error) { 852 printf("%s: error %d creating mailbox DMA maps\n", 853 isp->isp_name, error); 854 return (1); 855 } 856 } 857 if (IS_FC(isp)) { 858 fcparam *fcp = (fcparam *) isp->isp_param; 859 fcp->isp_scratch = base + 860 ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 861 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 862 im.error = 0; 863 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 864 fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0); 865 if (im.error) { 866 printf("%s: error %d loading FC scratch area\n", 867 isp->isp_name, im.error); 868 return (1); 869 } 870 } 871 return (0); 872} 873 874static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 875typedef struct { 876 struct ispsoftc *isp; 877 ISP_SCSI_XFER_T *ccb; 878 ispreq_t *rq; 879 u_int8_t *iptrp; 880 u_int8_t optr; 881 u_int error; 882} mush_t; 883 884#define MUSHERR_NOQENTRIES -2 885 886static void 887dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 888{ 889 mush_t *mp; 890 ISP_SCSI_XFER_T *ccb; 891 struct ispsoftc *isp; 892 struct isp_pcisoftc *pci; 893 bus_dmamap_t *dp; 894 bus_dma_segment_t *eseg; 895 ispreq_t *rq; 896 u_int8_t *iptrp; 897 u_int8_t optr; 898 ispcontreq_t *crq; 899 int drq, seglim, datalen; 900 901 mp = (mush_t *) arg; 902 if (error) { 903 mp->error = error; 904 return; 905 } 906 907 isp = mp->isp; 908 if (nseg < 1) { 909 printf("%s: zero or negative segment count\n", isp->isp_name); 910 mp->error = EFAULT; 911 return; 912 } 913 ccb = mp->ccb; 914 rq = mp->rq; 915 iptrp = mp->iptrp; 916 optr = mp->optr; 917 918 pci = (struct isp_pcisoftc *)isp; 919 dp = &pci->dmaps[rq->req_handle - 1]; 920 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 921 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 922 drq = REQFLAG_DATA_IN; 923 } else { 924 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 925 drq = REQFLAG_DATA_OUT; 926 } 927 928 datalen = XS_XFRLEN(ccb); 929 if (IS_FC(isp)) { 930 seglim = ISP_RQDSEG_T2; 931 ((ispreqt2_t *)rq)->req_totalcnt = datalen; 932 ((ispreqt2_t *)rq)->req_flags |= drq; 933 } else { 934 seglim = ISP_RQDSEG; 935 rq->req_flags |= drq; 936 } 937 938 eseg = dm_segs + nseg; 939 940 while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 941 if (IS_FC(isp)) { 942 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 943 rq2->req_dataseg[rq2->req_seg_count].ds_base = 944 dm_segs->ds_addr; 945 rq2->req_dataseg[rq2->req_seg_count].ds_count = 946 dm_segs->ds_len; 947 } else { 948 rq->req_dataseg[rq->req_seg_count].ds_base = 949 dm_segs->ds_addr; 950 rq->req_dataseg[rq->req_seg_count].ds_count = 951 dm_segs->ds_len; 952 } 953 datalen -= dm_segs->ds_len; 954#if 0 955 if (IS_FC(isp)) { 956 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 957 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 958 isp->isp_name, rq->req_seg_count, 959 rq2->req_dataseg[rq2->req_seg_count].ds_count, 960 rq2->req_dataseg[rq2->req_seg_count].ds_base); 961 } else { 962 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 963 isp->isp_name, rq->req_seg_count, 964 rq->req_dataseg[rq->req_seg_count].ds_count, 965 rq->req_dataseg[rq->req_seg_count].ds_base); 966 } 967#endif 968 rq->req_seg_count++; 969 dm_segs++; 970 } 971 972 while (datalen > 0 && dm_segs != eseg) { 973 crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 974 *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 975 if (*iptrp == optr) { 976#if 0 977 printf("%s: Request Queue Overflow++\n", isp->isp_name); 978#endif 979 mp->error = MUSHERR_NOQENTRIES; 980 return; 981 } 982 rq->req_header.rqs_entry_count++; 983 bzero((void *)crq, sizeof (*crq)); 984 crq->req_header.rqs_entry_count = 1; 985 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 986 987 seglim = 0; 988 while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 989 crq->req_dataseg[seglim].ds_base = 990 dm_segs->ds_addr; 991 crq->req_dataseg[seglim].ds_count = 992 dm_segs->ds_len; 993#if 0 994 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 995 isp->isp_name, rq->req_header.rqs_entry_count-1, 996 seglim, crq->req_dataseg[seglim].ds_count, 997 crq->req_dataseg[seglim].ds_base); 998#endif 999 rq->req_seg_count++; 1000 dm_segs++; 1001 seglim++; 1002 datalen -= dm_segs->ds_len; 1003 } 1004 } 1005} 1006 1007static int 1008isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 1009 u_int8_t *iptrp, u_int8_t optr) 1010{ 1011 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1012 struct ccb_hdr *ccb_h; 1013 struct ccb_scsiio *csio; 1014 bus_dmamap_t *dp = NULL; 1015 mush_t mush, *mp; 1016 1017 csio = (struct ccb_scsiio *) ccb; 1018 ccb_h = &csio->ccb_h; 1019 1020 if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 1021 rq->req_seg_count = 1; 1022 return (CMD_QUEUED); 1023 } 1024 1025 /* 1026 * Do a virtual grapevine step to collect info for 1027 * the callback dma allocation that we have to use... 1028 */ 1029 mp = &mush; 1030 mp->isp = isp; 1031 mp->ccb = ccb; 1032 mp->rq = rq; 1033 mp->iptrp = iptrp; 1034 mp->optr = optr; 1035 mp->error = 0; 1036 1037 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 1038 if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 1039 int error, s; 1040 1041 dp = &pci->dmaps[rq->req_handle - 1]; 1042 s = splsoftvm(); 1043 error = bus_dmamap_load(pci->parent_dmat, *dp, 1044 csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 1045 if (error == EINPROGRESS) { 1046 bus_dmamap_unload(pci->parent_dmat, *dp); 1047 mp->error = EINVAL; 1048 printf("%s: deferred dma allocation not " 1049 "supported\n", isp->isp_name); 1050 } else if (error && mp->error == 0) { 1051#ifdef DIAGNOSTIC 1052 printf("%s: error %d in dma mapping code\n", 1053 isp->isp_name, error); 1054#endif 1055 mp->error = error; 1056 } 1057 splx(s); 1058 } else { 1059 /* Pointer to physical buffer */ 1060 struct bus_dma_segment seg; 1061 seg.ds_addr = (bus_addr_t)csio->data_ptr; 1062 seg.ds_len = csio->dxfer_len; 1063 dma2(mp, &seg, 1, 0); 1064 } 1065 } else { 1066 struct bus_dma_segment *segs; 1067 1068 if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 1069 printf("%s: Physical segment pointers unsupported", 1070 isp->isp_name); 1071 mp->error = EINVAL; 1072 } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 1073 printf("%s: Virtual segment addresses unsupported", 1074 isp->isp_name); 1075 mp->error = EINVAL; 1076 } else { 1077 /* Just use the segments provided */ 1078 segs = (struct bus_dma_segment *) csio->data_ptr; 1079 dma2(mp, segs, csio->sglist_cnt, 0); 1080 } 1081 } 1082 if (mp->error) { 1083 int retval = CMD_COMPLETE; 1084 if (mp->error == MUSHERR_NOQENTRIES) { 1085 retval = CMD_EAGAIN; 1086 } else if (mp->error == EFBIG) { 1087 XS_SETERR(csio, CAM_REQ_TOO_BIG); 1088 } else if (mp->error == EINVAL) { 1089 XS_SETERR(csio, CAM_REQ_INVALID); 1090 } else { 1091 XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 1092 } 1093 return (retval); 1094 } else { 1095 /* 1096 * Check to see if we weren't cancelled while sleeping on 1097 * getting DMA resources... 1098 */ 1099 if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 1100 if (dp) { 1101 bus_dmamap_unload(pci->parent_dmat, *dp); 1102 } 1103 return (CMD_COMPLETE); 1104 } 1105 return (CMD_QUEUED); 1106 } 1107} 1108 1109static void 1110isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, 1111 u_int32_t handle) 1112{ 1113 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1114 bus_dmamap_t *dp = &pci->dmaps[handle]; 1115 1116 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1117 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 1118 } else { 1119 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 1120 } 1121 bus_dmamap_unload(pci->parent_dmat, *dp); 1122} 1123 1124 1125static void 1126isp_pci_reset1(struct ispsoftc *isp) 1127{ 1128 /* Make sure the BIOS is disabled */ 1129 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 1130} 1131 1132static void 1133isp_pci_dumpregs(struct ispsoftc *isp) 1134{ 1135 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1136 printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1137 pci_conf_read(pci->pci_id, PCIR_COMMAND)); 1138}
| 580 581 i >>= 5; 582 i &= 0x7; 583 584 /* 585 * This isn't very random, but it's the best we can do for 586 * the real edge case of cards that don't have WWNs. 587 */ 588 isp->isp_osinfo.seed += ((int) cfid->bus) << 16; 589 isp->isp_osinfo.seed += ((int) cfid->slot) << 8; 590 isp->isp_osinfo.seed += ((int) cfid->func); 591 while (version[i]) 592 isp->isp_osinfo.seed += (int) version[i++]; 593 isp->isp_osinfo.seed <<= 8; 594 isp->isp_osinfo.seed += (unit + 1); 595 } 596 597 ISP_LOCK(isp); 598 isp_reset(isp); 599 if (isp->isp_state != ISP_RESETSTATE) { 600 (void) pci_unmap_int(cfid); 601 ISP_UNLOCK(isp); 602 free(pcs, M_DEVBUF); 603 return; 604 } 605 isp_init(isp); 606 if (isp->isp_state != ISP_INITSTATE) { 607 /* If we're a Fibre Channel Card, we allow deferred attach */ 608 if (IS_SCSI(isp)) { 609 isp_uninit(isp); 610 (void) pci_unmap_int(cfid); /* Does nothing */ 611 ISP_UNLOCK(isp); 612 free(pcs, M_DEVBUF); 613 return; 614 } 615 } 616 isp_attach(isp); 617 if (isp->isp_state != ISP_RUNSTATE) { 618 /* If we're a Fibre Channel Card, we allow deferred attach */ 619 if (IS_SCSI(isp)) { 620 isp_uninit(isp); 621 (void) pci_unmap_int(cfid); /* Does nothing */ 622 ISP_UNLOCK(isp); 623 free(pcs, M_DEVBUF); 624 return; 625 } 626 } 627 ISP_UNLOCK(isp); 628#ifdef __alpha__ 629 /* 630 * THIS SHOULD NOT HAVE TO BE HERE 631 */ 632 alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim); 633#endif 634} 635 636static u_int16_t 637isp_pci_rd_reg(isp, regoff) 638 struct ispsoftc *isp; 639 int regoff; 640{ 641 u_int16_t rv; 642 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 643 int offset, oldconf = 0; 644 645 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 646 /* 647 * We will assume that someone has paused the RISC processor. 648 */ 649 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 650 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 651 } 652 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 653 offset += (regoff & 0xff); 654 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 655 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 656 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 657 } 658 return (rv); 659} 660 661static void 662isp_pci_wr_reg(isp, regoff, val) 663 struct ispsoftc *isp; 664 int regoff; 665 u_int16_t val; 666{ 667 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 668 int offset, oldconf = 0; 669 670 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 671 /* 672 * We will assume that someone has paused the RISC processor. 673 */ 674 oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 675 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 676 } 677 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 678 offset += (regoff & 0xff); 679 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 680 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 681 isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 682 } 683} 684 685#ifndef ISP_DISABLE_1080_SUPPORT 686static u_int16_t 687isp_pci_rd_reg_1080(isp, regoff) 688 struct ispsoftc *isp; 689 int regoff; 690{ 691 u_int16_t rv; 692 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 693 int offset, oc = 0; 694 695 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 696 /* 697 * We will assume that someone has paused the RISC processor. 698 */ 699 oc = isp_pci_rd_reg(isp, BIU_CONF1); 700 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 701 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 702 oc = isp_pci_rd_reg(isp, BIU_CONF1); 703 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 704 } 705 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 706 offset += (regoff & 0xff); 707 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 708 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 709 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 710 isp_pci_wr_reg(isp, BIU_CONF1, oc); 711 } 712 return (rv); 713} 714 715static void 716isp_pci_wr_reg_1080(isp, regoff, val) 717 struct ispsoftc *isp; 718 int regoff; 719 u_int16_t val; 720{ 721 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 722 int offset, oc = 0; 723 724 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 725 /* 726 * We will assume that someone has paused the RISC processor. 727 */ 728 oc = isp_pci_rd_reg(isp, BIU_CONF1); 729 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 730 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 731 oc = isp_pci_rd_reg(isp, BIU_CONF1); 732 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 733 } 734 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 735 offset += (regoff & 0xff); 736 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 737 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 738 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 739 isp_pci_wr_reg(isp, BIU_CONF1, oc); 740 } 741} 742#endif 743 744 745static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 746static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 747static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 748 749struct imush { 750 struct ispsoftc *isp; 751 int error; 752}; 753 754static void 755isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 756{ 757 struct imush *imushp = (struct imush *) arg; 758 if (error) { 759 imushp->error = error; 760 } else { 761 imushp->isp->isp_rquest_dma = segs->ds_addr; 762 } 763} 764 765static void 766isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 767{ 768 struct imush *imushp = (struct imush *) arg; 769 if (error) { 770 imushp->error = error; 771 } else { 772 imushp->isp->isp_result_dma = segs->ds_addr; 773 } 774} 775 776static void 777isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 778{ 779 struct imush *imushp = (struct imush *) arg; 780 if (error) { 781 imushp->error = error; 782 } else { 783 fcparam *fcp = imushp->isp->isp_param; 784 fcp->isp_scdma = segs->ds_addr; 785 } 786} 787 788static int 789isp_pci_mbxdma(struct ispsoftc *isp) 790{ 791 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 792 caddr_t base; 793 u_int32_t len; 794 int i, error; 795 bus_size_t lim; 796 struct imush im; 797 798 799 if (IS_FC(isp) || IS_1080(isp) || IS_12X0(isp)) 800 lim = BUS_SPACE_MAXADDR + 1; 801 else 802 lim = BUS_SPACE_MAXADDR_24BIT + 1; 803 804 /* 805 * Allocate and map the request, result queues, plus FC scratch area. 806 */ 807 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 808 len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 809 if (IS_FC(isp)) { 810 len += ISP2100_SCRLEN; 811 } 812 if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim, 813 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, 814 BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { 815 printf("%s: cannot create a dma tag for control spaces\n", 816 isp->isp_name); 817 return (1); 818 } 819 if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 820 BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 821 printf("%s: cannot allocate %d bytes of CCB memory\n", 822 isp->isp_name, len); 823 return (1); 824 } 825 826 isp->isp_rquest = base; 827 im.isp = isp; 828 im.error = 0; 829 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 830 ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, &im, 0); 831 if (im.error) { 832 printf("%s: error %d loading dma map for DMA request queue\n", 833 isp->isp_name, im.error); 834 return (1); 835 } 836 isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 837 im.error = 0; 838 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 839 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, &im, 0); 840 if (im.error) { 841 printf("%s: error %d loading dma map for DMA result queue\n", 842 isp->isp_name, im.error); 843 return (1); 844 } 845 846 /* 847 * Use this opportunity to initialize/create data DMA maps. 848 */ 849 for (i = 0; i < MAXISPREQUEST; i++) { 850 error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 851 if (error) { 852 printf("%s: error %d creating mailbox DMA maps\n", 853 isp->isp_name, error); 854 return (1); 855 } 856 } 857 if (IS_FC(isp)) { 858 fcparam *fcp = (fcparam *) isp->isp_param; 859 fcp->isp_scratch = base + 860 ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 861 ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 862 im.error = 0; 863 bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 864 fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0); 865 if (im.error) { 866 printf("%s: error %d loading FC scratch area\n", 867 isp->isp_name, im.error); 868 return (1); 869 } 870 } 871 return (0); 872} 873 874static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 875typedef struct { 876 struct ispsoftc *isp; 877 ISP_SCSI_XFER_T *ccb; 878 ispreq_t *rq; 879 u_int8_t *iptrp; 880 u_int8_t optr; 881 u_int error; 882} mush_t; 883 884#define MUSHERR_NOQENTRIES -2 885 886static void 887dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 888{ 889 mush_t *mp; 890 ISP_SCSI_XFER_T *ccb; 891 struct ispsoftc *isp; 892 struct isp_pcisoftc *pci; 893 bus_dmamap_t *dp; 894 bus_dma_segment_t *eseg; 895 ispreq_t *rq; 896 u_int8_t *iptrp; 897 u_int8_t optr; 898 ispcontreq_t *crq; 899 int drq, seglim, datalen; 900 901 mp = (mush_t *) arg; 902 if (error) { 903 mp->error = error; 904 return; 905 } 906 907 isp = mp->isp; 908 if (nseg < 1) { 909 printf("%s: zero or negative segment count\n", isp->isp_name); 910 mp->error = EFAULT; 911 return; 912 } 913 ccb = mp->ccb; 914 rq = mp->rq; 915 iptrp = mp->iptrp; 916 optr = mp->optr; 917 918 pci = (struct isp_pcisoftc *)isp; 919 dp = &pci->dmaps[rq->req_handle - 1]; 920 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 921 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 922 drq = REQFLAG_DATA_IN; 923 } else { 924 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 925 drq = REQFLAG_DATA_OUT; 926 } 927 928 datalen = XS_XFRLEN(ccb); 929 if (IS_FC(isp)) { 930 seglim = ISP_RQDSEG_T2; 931 ((ispreqt2_t *)rq)->req_totalcnt = datalen; 932 ((ispreqt2_t *)rq)->req_flags |= drq; 933 } else { 934 seglim = ISP_RQDSEG; 935 rq->req_flags |= drq; 936 } 937 938 eseg = dm_segs + nseg; 939 940 while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 941 if (IS_FC(isp)) { 942 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 943 rq2->req_dataseg[rq2->req_seg_count].ds_base = 944 dm_segs->ds_addr; 945 rq2->req_dataseg[rq2->req_seg_count].ds_count = 946 dm_segs->ds_len; 947 } else { 948 rq->req_dataseg[rq->req_seg_count].ds_base = 949 dm_segs->ds_addr; 950 rq->req_dataseg[rq->req_seg_count].ds_count = 951 dm_segs->ds_len; 952 } 953 datalen -= dm_segs->ds_len; 954#if 0 955 if (IS_FC(isp)) { 956 ispreqt2_t *rq2 = (ispreqt2_t *)rq; 957 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 958 isp->isp_name, rq->req_seg_count, 959 rq2->req_dataseg[rq2->req_seg_count].ds_count, 960 rq2->req_dataseg[rq2->req_seg_count].ds_base); 961 } else { 962 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 963 isp->isp_name, rq->req_seg_count, 964 rq->req_dataseg[rq->req_seg_count].ds_count, 965 rq->req_dataseg[rq->req_seg_count].ds_base); 966 } 967#endif 968 rq->req_seg_count++; 969 dm_segs++; 970 } 971 972 while (datalen > 0 && dm_segs != eseg) { 973 crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 974 *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 975 if (*iptrp == optr) { 976#if 0 977 printf("%s: Request Queue Overflow++\n", isp->isp_name); 978#endif 979 mp->error = MUSHERR_NOQENTRIES; 980 return; 981 } 982 rq->req_header.rqs_entry_count++; 983 bzero((void *)crq, sizeof (*crq)); 984 crq->req_header.rqs_entry_count = 1; 985 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 986 987 seglim = 0; 988 while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 989 crq->req_dataseg[seglim].ds_base = 990 dm_segs->ds_addr; 991 crq->req_dataseg[seglim].ds_count = 992 dm_segs->ds_len; 993#if 0 994 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 995 isp->isp_name, rq->req_header.rqs_entry_count-1, 996 seglim, crq->req_dataseg[seglim].ds_count, 997 crq->req_dataseg[seglim].ds_base); 998#endif 999 rq->req_seg_count++; 1000 dm_segs++; 1001 seglim++; 1002 datalen -= dm_segs->ds_len; 1003 } 1004 } 1005} 1006 1007static int 1008isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 1009 u_int8_t *iptrp, u_int8_t optr) 1010{ 1011 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1012 struct ccb_hdr *ccb_h; 1013 struct ccb_scsiio *csio; 1014 bus_dmamap_t *dp = NULL; 1015 mush_t mush, *mp; 1016 1017 csio = (struct ccb_scsiio *) ccb; 1018 ccb_h = &csio->ccb_h; 1019 1020 if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 1021 rq->req_seg_count = 1; 1022 return (CMD_QUEUED); 1023 } 1024 1025 /* 1026 * Do a virtual grapevine step to collect info for 1027 * the callback dma allocation that we have to use... 1028 */ 1029 mp = &mush; 1030 mp->isp = isp; 1031 mp->ccb = ccb; 1032 mp->rq = rq; 1033 mp->iptrp = iptrp; 1034 mp->optr = optr; 1035 mp->error = 0; 1036 1037 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 1038 if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 1039 int error, s; 1040 1041 dp = &pci->dmaps[rq->req_handle - 1]; 1042 s = splsoftvm(); 1043 error = bus_dmamap_load(pci->parent_dmat, *dp, 1044 csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 1045 if (error == EINPROGRESS) { 1046 bus_dmamap_unload(pci->parent_dmat, *dp); 1047 mp->error = EINVAL; 1048 printf("%s: deferred dma allocation not " 1049 "supported\n", isp->isp_name); 1050 } else if (error && mp->error == 0) { 1051#ifdef DIAGNOSTIC 1052 printf("%s: error %d in dma mapping code\n", 1053 isp->isp_name, error); 1054#endif 1055 mp->error = error; 1056 } 1057 splx(s); 1058 } else { 1059 /* Pointer to physical buffer */ 1060 struct bus_dma_segment seg; 1061 seg.ds_addr = (bus_addr_t)csio->data_ptr; 1062 seg.ds_len = csio->dxfer_len; 1063 dma2(mp, &seg, 1, 0); 1064 } 1065 } else { 1066 struct bus_dma_segment *segs; 1067 1068 if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 1069 printf("%s: Physical segment pointers unsupported", 1070 isp->isp_name); 1071 mp->error = EINVAL; 1072 } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 1073 printf("%s: Virtual segment addresses unsupported", 1074 isp->isp_name); 1075 mp->error = EINVAL; 1076 } else { 1077 /* Just use the segments provided */ 1078 segs = (struct bus_dma_segment *) csio->data_ptr; 1079 dma2(mp, segs, csio->sglist_cnt, 0); 1080 } 1081 } 1082 if (mp->error) { 1083 int retval = CMD_COMPLETE; 1084 if (mp->error == MUSHERR_NOQENTRIES) { 1085 retval = CMD_EAGAIN; 1086 } else if (mp->error == EFBIG) { 1087 XS_SETERR(csio, CAM_REQ_TOO_BIG); 1088 } else if (mp->error == EINVAL) { 1089 XS_SETERR(csio, CAM_REQ_INVALID); 1090 } else { 1091 XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 1092 } 1093 return (retval); 1094 } else { 1095 /* 1096 * Check to see if we weren't cancelled while sleeping on 1097 * getting DMA resources... 1098 */ 1099 if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 1100 if (dp) { 1101 bus_dmamap_unload(pci->parent_dmat, *dp); 1102 } 1103 return (CMD_COMPLETE); 1104 } 1105 return (CMD_QUEUED); 1106 } 1107} 1108 1109static void 1110isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, 1111 u_int32_t handle) 1112{ 1113 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1114 bus_dmamap_t *dp = &pci->dmaps[handle]; 1115 1116 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1117 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 1118 } else { 1119 bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 1120 } 1121 bus_dmamap_unload(pci->parent_dmat, *dp); 1122} 1123 1124 1125static void 1126isp_pci_reset1(struct ispsoftc *isp) 1127{ 1128 /* Make sure the BIOS is disabled */ 1129 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 1130} 1131 1132static void 1133isp_pci_dumpregs(struct ispsoftc *isp) 1134{ 1135 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1136 printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1137 pci_conf_read(pci->pci_id, PCIR_COMMAND)); 1138}
|