Annotation of sys/dev/pci/isp_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: isp_pci.c,v 1.39 2007/02/28 19:40:38 kettenis Exp $ */
! 2: /*
! 3: * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
! 4: *
! 5: *---------------------------------------
! 6: * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
! 7: * NASA/Ames Research Center
! 8: * All rights reserved.
! 9: *---------------------------------------
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice immediately at the beginning of the file, without modification,
! 16: * this list of conditions, and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. The name of the author may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 27: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: *
! 35: */
! 36:
! 37: #include <dev/ic/isp_openbsd.h>
! 38:
! 39: #include <dev/pci/pcireg.h>
! 40: #include <dev/pci/pcivar.h>
! 41: #include <dev/pci/pcidevs.h>
! 42:
! 43: #ifdef __sparc64__
! 44: #include <dev/ofw/openfirm.h>
! 45: #endif
! 46:
! 47: static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int);
! 48: static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t);
! 49: #if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT))
! 50: static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int);
! 51: static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t);
! 52: #endif
! 53: static int
! 54: isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
! 55: #ifndef ISP_DISABLE_2300_SUPPORT
! 56: static int
! 57: isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
! 58: #endif
! 59: static int isp_pci_mbxdma(struct ispsoftc *);
! 60: static int isp_pci_dmasetup(struct ispsoftc *, struct scsi_xfer *,
! 61: ispreq_t *, u_int16_t *, u_int16_t);
! 62: static void
! 63: isp_pci_dmateardown (struct ispsoftc *, struct scsi_xfer *, u_int16_t);
! 64: static void isp_pci_reset1 (struct ispsoftc *);
! 65: static void isp_pci_dumpregs (struct ispsoftc *, const char *);
! 66: static int isp_pci_intr (void *);
! 67:
! 68: #ifdef ISP_COMPILE_FW
! 69: #define ISP_COMPILE_1040_FW 1
! 70: #define ISP_COMPILE_1080_FW 1
! 71: #define ISP_COMPILE_12160_FW 1
! 72: #define ISP_COMPILE_2100_FW 1
! 73: #define ISP_COMPILE_2200_FW 1
! 74: #define ISP_COMPILE_2300_FW 1
! 75: #endif
! 76:
! 77: #if defined(ISP_DISABLE_1040_SUPPORT) || !defined(ISP_COMPILE_1040_FW)
! 78: #define ISP_1040_RISC_CODE NULL
! 79: #else
! 80: #define ISP_1040_RISC_CODE (u_int16_t *) isp_1040_risc_code
! 81: #include <dev/microcode/isp/asm_1040.h>
! 82: #endif
! 83:
! 84: #if defined(ISP_DISABLE_1080_SUPPORT) || !defined(ISP_COMPILE_1080_FW)
! 85: #define ISP_1080_RISC_CODE NULL
! 86: #else
! 87: #define ISP_1080_RISC_CODE (u_int16_t *) isp_1080_risc_code
! 88: #include <dev/microcode/isp/asm_1080.h>
! 89: #endif
! 90:
! 91: #if defined(ISP_DISABLE_12160_SUPPORT) || !defined(ISP_COMPILE_12160_FW)
! 92: #define ISP_12160_RISC_CODE (u_int16_t *) NULL
! 93: #else
! 94: #define ISP_12160_RISC_CODE (u_int16_t *) isp_12160_risc_code
! 95: #include <dev/microcode/isp/asm_12160.h>
! 96: #endif
! 97:
! 98: #if defined(ISP_DISABLE_2100_SUPPORT) || !defined(ISP_COMPILE_2100_FW)
! 99: #define ISP_2100_RISC_CODE NULL
! 100: #else
! 101: #define ISP_2100_RISC_CODE (u_int16_t *) isp_2100_risc_code
! 102: #include <dev/microcode/isp/asm_2100.h>
! 103: #endif
! 104:
! 105: #if defined(ISP_DISABLE_2200_SUPPORT) || !defined(ISP_COMPILE_2200_FW)
! 106: #define ISP_2200_RISC_CODE NULL
! 107: #else
! 108: #define ISP_2200_RISC_CODE (u_int16_t *) isp_2200_risc_code
! 109: #include <dev/microcode/isp/asm_2200.h>
! 110: #endif
! 111:
! 112: #if defined(ISP_DISABLE_2300_SUPPORT) || !defined(ISP_COMPILE_2300_FW)
! 113: #define ISP_2300_RISC_CODE NULL
! 114: #else
! 115: #define ISP_2300_RISC_CODE (u_int16_t *) isp_2300_risc_code
! 116: #include <dev/microcode/isp/asm_2300.h>
! 117: #endif
! 118:
! 119: #ifndef ISP_DISABLE_1020_SUPPORT
! 120: static struct ispmdvec mdvec = {
! 121: isp_pci_rd_isr,
! 122: isp_pci_rd_reg,
! 123: isp_pci_wr_reg,
! 124: isp_pci_mbxdma,
! 125: isp_pci_dmasetup,
! 126: isp_pci_dmateardown,
! 127: NULL,
! 128: isp_pci_reset1,
! 129: isp_pci_dumpregs,
! 130: ISP_1040_RISC_CODE,
! 131: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
! 132: };
! 133: #endif
! 134:
! 135: #ifndef ISP_DISABLE_1080_SUPPORT
! 136: static struct ispmdvec mdvec_1080 = {
! 137: isp_pci_rd_isr,
! 138: isp_pci_rd_reg_1080,
! 139: isp_pci_wr_reg_1080,
! 140: isp_pci_mbxdma,
! 141: isp_pci_dmasetup,
! 142: isp_pci_dmateardown,
! 143: NULL,
! 144: isp_pci_reset1,
! 145: isp_pci_dumpregs,
! 146: ISP_1080_RISC_CODE,
! 147: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
! 148: };
! 149: #endif
! 150:
! 151: #ifndef ISP_DISABLE_12160_SUPPORT
! 152: static struct ispmdvec mdvec_12160 = {
! 153: isp_pci_rd_isr,
! 154: isp_pci_rd_reg_1080,
! 155: isp_pci_wr_reg_1080,
! 156: isp_pci_mbxdma,
! 157: isp_pci_dmasetup,
! 158: isp_pci_dmateardown,
! 159: NULL,
! 160: isp_pci_reset1,
! 161: isp_pci_dumpregs,
! 162: ISP_12160_RISC_CODE,
! 163: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
! 164: };
! 165: #endif
! 166:
! 167: #ifndef ISP_DISABLE_2100_SUPPORT
! 168: static struct ispmdvec mdvec_2100 = {
! 169: isp_pci_rd_isr,
! 170: isp_pci_rd_reg,
! 171: isp_pci_wr_reg,
! 172: isp_pci_mbxdma,
! 173: isp_pci_dmasetup,
! 174: isp_pci_dmateardown,
! 175: NULL,
! 176: isp_pci_reset1,
! 177: isp_pci_dumpregs,
! 178: ISP_2100_RISC_CODE
! 179: };
! 180: #endif
! 181:
! 182: #ifndef ISP_DISABLE_2200_SUPPORT
! 183: static struct ispmdvec mdvec_2200 = {
! 184: isp_pci_rd_isr,
! 185: isp_pci_rd_reg,
! 186: isp_pci_wr_reg,
! 187: isp_pci_mbxdma,
! 188: isp_pci_dmasetup,
! 189: isp_pci_dmateardown,
! 190: NULL,
! 191: isp_pci_reset1,
! 192: isp_pci_dumpregs,
! 193: ISP_2200_RISC_CODE
! 194: };
! 195: #endif
! 196:
! 197: #ifndef ISP_DISABLE_2300_SUPPORT
! 198: static struct ispmdvec mdvec_2300 = {
! 199: isp_pci_rd_isr_2300,
! 200: isp_pci_rd_reg,
! 201: isp_pci_wr_reg,
! 202: isp_pci_mbxdma,
! 203: isp_pci_dmasetup,
! 204: isp_pci_dmateardown,
! 205: NULL,
! 206: isp_pci_reset1,
! 207: isp_pci_dumpregs,
! 208: ISP_2300_RISC_CODE
! 209: };
! 210: #endif
! 211:
! 212: #ifndef PCI_VENDOR_QLOGIC
! 213: #define PCI_VENDOR_QLOGIC 0x1077
! 214: #endif
! 215:
! 216: #ifndef PCI_PRODUCT_QLOGIC_ISP1020
! 217: #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
! 218: #endif
! 219:
! 220: #ifndef PCI_PRODUCT_QLOGIC_ISP1080
! 221: #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080
! 222: #endif
! 223:
! 224: #ifndef PCI_PRODUCT_QLOGIC_ISP1240
! 225: #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240
! 226: #endif
! 227:
! 228: #ifndef PCI_PRODUCT_QLOGIC_ISP1280
! 229: #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280
! 230: #endif
! 231:
! 232: #ifndef PCI_PRODUCT_QLOGIC_ISP10160
! 233: #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016
! 234: #endif
! 235:
! 236: #ifndef PCI_PRODUCT_QLOGIC_ISP12160
! 237: #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216
! 238: #endif
! 239:
! 240: #ifndef PCI_PRODUCT_QLOGIC_ISP2100
! 241: #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
! 242: #endif
! 243:
! 244: #ifndef PCI_PRODUCT_QLOGIC_ISP2200
! 245: #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
! 246: #endif
! 247:
! 248: #ifndef PCI_PRODUCT_QLOGIC_ISP2300
! 249: #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300
! 250: #endif
! 251:
! 252: #ifndef PCI_PRODUCT_QLOGIC_ISP2312
! 253: #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312
! 254: #endif
! 255:
! 256: #ifndef PCI_PRODUCT_QLOGIC_ISP6312
! 257: #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312
! 258: #endif
! 259:
! 260: #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
! 261:
! 262: #define PCI_QLOGIC_ISP1080 \
! 263: ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
! 264:
! 265: #define PCI_QLOGIC_ISP1240 \
! 266: ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
! 267:
! 268: #define PCI_QLOGIC_ISP1280 \
! 269: ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC)
! 270:
! 271: #define PCI_QLOGIC_ISP10160 \
! 272: ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC)
! 273:
! 274: #define PCI_QLOGIC_ISP12160 \
! 275: ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC)
! 276:
! 277: #define PCI_QLOGIC_ISP2100 \
! 278: ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
! 279:
! 280: #define PCI_QLOGIC_ISP2200 \
! 281: ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
! 282:
! 283: #define PCI_QLOGIC_ISP2300 \
! 284: ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC)
! 285:
! 286: #define PCI_QLOGIC_ISP2312 \
! 287: ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
! 288:
! 289: #define PCI_QLOGIC_ISP6312 \
! 290: ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC)
! 291:
! 292: /*
! 293: * Odd case for some AMI raid cards... We need to *not* attach to this.
! 294: */
! 295: #define AMI_RAID_SUBVENDOR_ID 0x101e
! 296:
! 297:
! 298: #define IO_MAP_REG 0x10
! 299: #define MEM_MAP_REG 0x14
! 300: #define PCIR_ROMADDR 0x30
! 301:
! 302: #define PCI_DFLT_LTNCY 0x40
! 303: #define PCI_DFLT_LNSZ 0x10
! 304:
! 305: #ifndef SCSI_ISP_PREFER_MEM_MAP
! 306: #ifdef __alpha__
! 307: #define SCSI_ISP_PREFER_MEM_MAP 1
! 308: #else
! 309: #define SCSI_ISP_PREFER_MEM_MAP 0
! 310: #endif
! 311: #endif
! 312:
! 313: #ifndef BUS_DMA_COHERENT
! 314: #define BUS_DMA_COHERENT BUS_DMAMEM_NOSYNC
! 315: #endif
! 316:
! 317: static int isp_pci_probe (struct device *, void *, void *);
! 318: static void isp_pci_attach (struct device *, struct device *, void *);
! 319:
! 320: struct isp_pcisoftc {
! 321: struct ispsoftc pci_isp;
! 322: pci_chipset_tag_t pci_pc;
! 323: pcitag_t pci_tag;
! 324: bus_space_tag_t pci_st;
! 325: bus_space_handle_t pci_sh;
! 326: bus_dmamap_t *pci_xfer_dmap;
! 327: void * pci_ih;
! 328: int16_t pci_poff[_NREG_BLKS];
! 329: };
! 330:
! 331: struct cfattach isp_pci_ca = {
! 332: sizeof (struct isp_pcisoftc), isp_pci_probe, isp_pci_attach
! 333: };
! 334:
! 335: #ifdef DEBUG
! 336: const char vstring[] =
! 337: "Qlogic ISP Driver, NetBSD (pci) Platform Version %d.%d Core Version %d.%d";
! 338: #endif
! 339:
! 340: const struct pci_matchid ispdev[] = {
! 341: #ifndef ISP_DISABLE_1020_SUPPORT
! 342: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 },
! 343: #endif
! 344: #ifndef ISP_DISABLE_1080_SUPPORT
! 345: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 },
! 346: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 },
! 347: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 },
! 348: #endif
! 349: #ifndef ISP_DISABLE_12160_SUPPORT
! 350: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 },
! 351: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 },
! 352: #endif
! 353: #ifndef ISP_DISABLE_2100_SUPPORT
! 354: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100 },
! 355: #endif
! 356: #ifndef ISP_DISABLE_2200_SUPPORT
! 357: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2200 },
! 358: #endif
! 359: #ifndef ISP_DISABLE_2300_SUPPORT
! 360: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2300 },
! 361: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2312 },
! 362: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6312 },
! 363: #endif
! 364: { 0, 0 }
! 365: };
! 366:
! 367: static int
! 368: isp_pci_probe(struct device *parent, void *match, void *aux)
! 369: {
! 370: struct pci_attach_args *pa = aux;
! 371:
! 372: #ifndef ISP_DISABLE_12160_SUPPORT
! 373: /*
! 374: * Sigh. Check for subvendor id match here. Too bad we
! 375: * can't give an exclude mask in matchbyid.
! 376: */
! 377: if (pa->pa_id == PCI_QLOGIC_ISP12160) {
! 378: pcireg_t subvid =
! 379: pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBVEND_0);
! 380: if (PCI_VENDOR(subvid) == AMI_RAID_SUBVENDOR_ID) {
! 381: return (0);
! 382: }
! 383: }
! 384: #endif
! 385: return (pci_matchbyid(pa, ispdev, sizeof(ispdev)/sizeof(ispdev[0])));
! 386: }
! 387:
! 388:
! 389: static void
! 390: isp_pci_attach(struct device *parent, struct device *self, void *aux)
! 391: {
! 392: #ifdef DEBUG
! 393: static char oneshot = 1;
! 394: #endif
! 395: static const char nomem[] = ": no mem for sdparam table\n";
! 396: u_int32_t data, rev, linesz = PCI_DFLT_LNSZ;
! 397: struct pci_attach_args *pa = aux;
! 398: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) self;
! 399: struct ispsoftc *isp = &pcs->pci_isp;
! 400: bus_space_tag_t st, iot, memt;
! 401: bus_space_handle_t sh, ioh, memh;
! 402: pci_intr_handle_t ih;
! 403: const char *intrstr;
! 404: int ioh_valid, memh_valid;
! 405: bus_size_t iosize, msize;
! 406: u_int32_t confopts = 0;
! 407:
! 408: ioh_valid = memh_valid = 0;
! 409:
! 410: #if SCSI_ISP_PREFER_MEM_MAP == 1
! 411: if (pci_mapreg_map(pa, MEM_MAP_REG, PCI_MAPREG_TYPE_MEM, 0,
! 412: &memt, &memh, NULL, &msize, 0)) {
! 413: printf(": can't map mem space\n");
! 414: } else {
! 415: st = memt;
! 416: sh = memh;
! 417: memh_valid = 1;
! 418: }
! 419: if (memh_valid == 0) {
! 420: if (pci_mapreg_map(pa, IO_MAP_REG, PCI_MAPREG_TYPE_IO, 0,
! 421: &iot, &ioh, NULL, &iosize, 0)) {
! 422: } else {
! 423: st = iot;
! 424: sh = ioh;
! 425: ioh_valid = 1;
! 426: }
! 427: }
! 428: #else
! 429: if (pci_mapreg_map(pa, IO_MAP_REG, PCI_MAPREG_TYPE_IO, 0,
! 430: &iot, &ioh, NULL, &iosize, 0)) {
! 431: printf(": can't map i/o space\n");
! 432: } else {
! 433: st = iot;
! 434: sh = ioh;
! 435: ioh_valid = 1;
! 436: }
! 437: if (ioh_valid == 0) {
! 438: if (pci_mapreg_map(pa, MEM_MAP_REG, PCI_MAPREG_TYPE_MEM, 0,
! 439: &memt, &memh, NULL, &msize, 0)) {
! 440: printf(": can't map mem space\n");
! 441: } else {
! 442: st = memt;
! 443: sh = memh;
! 444: memh_valid = 1;
! 445: }
! 446: }
! 447: #endif
! 448: if (ioh_valid == 0 && memh_valid == 0) {
! 449: printf(": unable to map device registers\n");
! 450: return;
! 451: }
! 452: #if 0
! 453: printf("\n");
! 454: #endif
! 455:
! 456: pcs->pci_st = st;
! 457: pcs->pci_sh = sh;
! 458: pcs->pci_pc = pa->pa_pc;
! 459: pcs->pci_tag = pa->pa_tag;
! 460: pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
! 461: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
! 462: pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
! 463: pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
! 464: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
! 465: rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0xff;
! 466: #ifndef ISP_DISABLE_1020_SUPPORT
! 467: if (pa->pa_id == PCI_QLOGIC_ISP) {
! 468: isp->isp_mdvec = &mdvec;
! 469: isp->isp_type = ISP_HA_SCSI_UNKNOWN;
! 470: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
! 471: if (isp->isp_param == NULL) {
! 472: printf(nomem);
! 473: return;
! 474: }
! 475: bzero(isp->isp_param, sizeof (sdparam));
! 476: }
! 477: #endif
! 478: #ifndef ISP_DISABLE_1080_SUPPORT
! 479: if (pa->pa_id == PCI_QLOGIC_ISP1080) {
! 480: isp->isp_mdvec = &mdvec_1080;
! 481: isp->isp_type = ISP_HA_SCSI_1080;
! 482: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
! 483: if (isp->isp_param == NULL) {
! 484: printf(nomem);
! 485: return;
! 486: }
! 487: bzero(isp->isp_param, sizeof (sdparam));
! 488: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
! 489: ISP1080_DMA_REGS_OFF;
! 490: }
! 491: if (pa->pa_id == PCI_QLOGIC_ISP1240) {
! 492: isp->isp_mdvec = &mdvec_1080;
! 493: isp->isp_type = ISP_HA_SCSI_1240;
! 494: isp->isp_param = malloc(2 * sizeof (sdparam),
! 495: M_DEVBUF, M_NOWAIT);
! 496: if (isp->isp_param == NULL) {
! 497: printf(nomem);
! 498: return;
! 499: }
! 500: bzero(isp->isp_param, sizeof (sdparam));
! 501: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
! 502: ISP1080_DMA_REGS_OFF;
! 503: }
! 504: if (pa->pa_id == PCI_QLOGIC_ISP1280) {
! 505: isp->isp_mdvec = &mdvec_1080;
! 506: isp->isp_type = ISP_HA_SCSI_1280;
! 507: isp->isp_param = malloc(2 * sizeof (sdparam),
! 508: M_DEVBUF, M_NOWAIT);
! 509: if (isp->isp_param == NULL) {
! 510: printf(nomem);
! 511: return;
! 512: }
! 513: bzero(isp->isp_param, sizeof (sdparam));
! 514: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
! 515: ISP1080_DMA_REGS_OFF;
! 516: }
! 517: #endif
! 518: #ifndef ISP_DISABLE_12160_SUPPORT
! 519: if (pa->pa_id == PCI_QLOGIC_ISP10160) {
! 520: isp->isp_mdvec = &mdvec_12160;
! 521: isp->isp_type = ISP_HA_SCSI_10160;
! 522: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
! 523: if (isp->isp_param == NULL) {
! 524: printf(nomem);
! 525: return;
! 526: }
! 527: bzero(isp->isp_param, sizeof (sdparam));
! 528: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
! 529: ISP1080_DMA_REGS_OFF;
! 530: }
! 531: if (pa->pa_id == PCI_QLOGIC_ISP12160) {
! 532: isp->isp_mdvec = &mdvec_12160;
! 533: isp->isp_type = ISP_HA_SCSI_12160;
! 534: isp->isp_param = malloc(2 * sizeof (sdparam),
! 535: M_DEVBUF, M_NOWAIT);
! 536: if (isp->isp_param == NULL) {
! 537: printf(nomem);
! 538: return;
! 539: }
! 540: bzero(isp->isp_param, 2 * sizeof (sdparam));
! 541: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
! 542: ISP1080_DMA_REGS_OFF;
! 543: }
! 544: #endif
! 545: #ifndef ISP_DISABLE_2100_SUPPORT
! 546: if (pa->pa_id == PCI_QLOGIC_ISP2100) {
! 547: isp->isp_mdvec = &mdvec_2100;
! 548: isp->isp_type = ISP_HA_FC_2100;
! 549: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
! 550: if (isp->isp_param == NULL) {
! 551: printf(nomem);
! 552: return;
! 553: }
! 554: bzero(isp->isp_param, sizeof (fcparam));
! 555: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
! 556: PCI_MBOX_REGS2100_OFF;
! 557: if (rev < 3) {
! 558: /*
! 559: * XXX: Need to get the actual revision
! 560: * XXX: number of the 2100 FB. At any rate,
! 561: * XXX: lower cache line size for early revision
! 562: * XXX; boards.
! 563: */
! 564: linesz = 1;
! 565: }
! 566: }
! 567: #endif
! 568: #ifndef ISP_DISABLE_2200_SUPPORT
! 569: if (pa->pa_id == PCI_QLOGIC_ISP2200) {
! 570: isp->isp_mdvec = &mdvec_2200;
! 571: isp->isp_type = ISP_HA_FC_2200;
! 572: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
! 573: if (isp->isp_param == NULL) {
! 574: printf(nomem);
! 575: return;
! 576: }
! 577: bzero(isp->isp_param, sizeof (fcparam));
! 578: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
! 579: PCI_MBOX_REGS2100_OFF;
! 580: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
! 581: #ifdef __sparc64__
! 582: {
! 583: char name[32];
! 584:
! 585: bzero(name, sizeof(name));
! 586: OF_getprop(PCITAG_NODE(pa->pa_tag),
! 587: "name", name, sizeof(name));
! 588: if (strcmp(name, "SUNW,qlc") == 0)
! 589: confopts |= ISP_CFG_NONVRAM;
! 590: }
! 591: #endif
! 592: }
! 593: #endif
! 594: #ifndef ISP_DISABLE_2300_SUPPORT
! 595: if (pa->pa_id == PCI_QLOGIC_ISP2300 ||
! 596: pa->pa_id == PCI_QLOGIC_ISP2312 ||
! 597: pa->pa_id == PCI_QLOGIC_ISP6312) {
! 598: isp->isp_mdvec = &mdvec_2300;
! 599: if (pa->pa_id == PCI_QLOGIC_ISP2300) {
! 600: isp->isp_type = ISP_HA_FC_2300;
! 601: } else {
! 602: isp->isp_type = ISP_HA_FC_2312;
! 603: isp->isp_port = pa->pa_function;
! 604: }
! 605: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
! 606: if (isp->isp_param == NULL) {
! 607: printf(nomem);
! 608: return;
! 609: }
! 610: bzero(isp->isp_param, sizeof (fcparam));
! 611: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
! 612: PCI_MBOX_REGS2300_OFF;
! 613: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
! 614: }
! 615: #endif
! 616: /*
! 617: * Set up logging levels.
! 618: */
! 619: #ifdef ISP_LOGDEFAULT
! 620: isp->isp_dblev = ISP_LOGDEFAULT;
! 621: #else
! 622: isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
! 623: #ifdef SCSIDEBUG
! 624: isp->isp_dblev |= ISP_LOGDEBUG1|ISP_LOGDEBUG2;
! 625: #endif
! 626: #ifdef DEBUG
! 627: isp->isp_dblev |= ISP_LOGDEBUG0|ISP_LOGCONFIG|ISP_LOGINFO;
! 628: #endif
! 629: #endif
! 630:
! 631: #ifdef DEBUG
! 632: if (oneshot) {
! 633: oneshot = 0;
! 634: isp_prt(isp, ISP_LOGCONFIG, vstring,
! 635: ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
! 636: ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
! 637: }
! 638: #endif
! 639:
! 640: isp->isp_dmatag = pa->pa_dmat;
! 641: isp->isp_revision = rev;
! 642:
! 643: /*
! 644: * Make sure that command register set sanely.
! 645: */
! 646: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
! 647: if (IS_2300(isp)) { /* per QLogic errata */
! 648: data &= ~PCI_COMMAND_PARITY_ENABLE;
! 649: }
! 650: if (IS_23XX(isp)) {
! 651: isp->isp_touched = 1;
! 652: }
! 653: data |= PCI_COMMAND_INVALIDATE_ENABLE;
! 654:
! 655: /*
! 656: * Not so sure about these- but I think it's important that they get
! 657: * enabled......
! 658: */
! 659: data |= PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
! 660: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, data);
! 661:
! 662: /*
! 663: * Make sure that the latency timer, cache line size,
! 664: * and ROM is disabled.
! 665: */
! 666: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
! 667: data &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
! 668: data &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
! 669: data |= (0x40 << PCI_LATTIMER_SHIFT);
! 670: data |= (0x10 << PCI_CACHELINE_SHIFT);
! 671: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, data);
! 672:
! 673: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR);
! 674: data &= ~1;
! 675: pci_conf_write(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR, data);
! 676:
! 677: if (pci_intr_map(pa, &ih)) {
! 678: printf(": couldn't map interrupt\n");
! 679: free(isp->isp_param, M_DEVBUF);
! 680: return;
! 681: }
! 682: intrstr = pci_intr_string(pa->pa_pc, ih);
! 683: if (intrstr == NULL)
! 684: intrstr = "<I dunno>";
! 685: pcs->pci_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, isp_pci_intr,
! 686: isp, isp->isp_name);
! 687: if (pcs->pci_ih == NULL) {
! 688: printf(": couldn't establish interrupt at %s\n",
! 689: intrstr);
! 690: free(isp->isp_param, M_DEVBUF);
! 691: return;
! 692: }
! 693:
! 694: printf(": %s\n", intrstr);
! 695:
! 696: if (IS_FC(isp)) {
! 697: DEFAULT_NODEWWN(isp) = 0x400000007F000003ULL;
! 698: DEFAULT_PORTWWN(isp) = 0x400000007F000003ULL;
! 699: }
! 700:
! 701: isp->isp_confopts = confopts | self->dv_cfdata->cf_flags;
! 702: isp->isp_role = ISP_DEFAULT_ROLES;
! 703: ISP_LOCK(isp);
! 704: isp->isp_osinfo.no_mbox_ints = 1;
! 705: isp_reset(isp);
! 706: if (isp->isp_state != ISP_RESETSTATE) {
! 707: ISP_UNLOCK(isp);
! 708: free(isp->isp_param, M_DEVBUF);
! 709: return;
! 710: }
! 711: ENABLE_INTS(isp);
! 712: isp_init(isp);
! 713: if (isp->isp_state != ISP_INITSTATE) {
! 714: isp_uninit(isp);
! 715: ISP_UNLOCK(isp);
! 716: free(isp->isp_param, M_DEVBUF);
! 717: return;
! 718: }
! 719: /*
! 720: * Do Generic attach now.
! 721: */
! 722: isp_attach(isp);
! 723: if (isp->isp_state != ISP_RUNSTATE) {
! 724: isp_uninit(isp);
! 725: ISP_UNLOCK(isp);
! 726: free(isp->isp_param, M_DEVBUF);
! 727: } else {
! 728: ISP_UNLOCK(isp);
! 729: }
! 730: }
! 731:
! 732: #define IspVirt2Off(a, x) \
! 733: (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
! 734: _BLK_REG_SHFT] + ((x) & 0xff))
! 735:
! 736: #define BXR2(pcs, off) \
! 737: bus_space_read_2(pcs->pci_st, pcs->pci_sh, off)
! 738: #define BXW2(pcs, off, v) \
! 739: bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v)
! 740:
! 741:
! 742: static INLINE int
! 743: isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp)
! 744: {
! 745: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 746: u_int16_t val0, val1;
! 747: int i = 0;
! 748:
! 749: do {
! 750: val0 = BXR2(pcs, IspVirt2Off(isp, off));
! 751: val1 = BXR2(pcs, IspVirt2Off(isp, off));
! 752: } while (val0 != val1 && ++i < 1000);
! 753: if (val0 != val1) {
! 754: return (1);
! 755: }
! 756: *rp = val0;
! 757: return (0);
! 758: }
! 759:
! 760: static int
! 761: isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp,
! 762: u_int16_t *semap, u_int16_t *mbp)
! 763: {
! 764: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 765: u_int16_t isr, sema;
! 766:
! 767: if (IS_2100(isp)) {
! 768: if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) {
! 769: return (0);
! 770: }
! 771: if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) {
! 772: return (0);
! 773: }
! 774: } else {
! 775: isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR));
! 776: sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA));
! 777: }
! 778: isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
! 779: isr &= INT_PENDING_MASK(isp);
! 780: sema &= BIU_SEMA_LOCK;
! 781: if (isr == 0 && sema == 0) {
! 782: return (0);
! 783: }
! 784: *isrp = isr;
! 785: if ((*semap = sema) != 0) {
! 786: if (IS_2100(isp)) {
! 787: if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) {
! 788: return (0);
! 789: }
! 790: } else {
! 791: *mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0));
! 792: }
! 793: }
! 794: return (1);
! 795: }
! 796:
! 797: #ifndef ISP_DISABLE_2300_SUPPORT
! 798: static int
! 799: isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp,
! 800: u_int16_t *semap, u_int16_t *mbox0p)
! 801: {
! 802: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 803: u_int32_t r2hisr;
! 804:
! 805: if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR)) & BIU2100_ISR_RISC_INT)) {
! 806: *isrp = 0;
! 807: return (0);
! 808: }
! 809: r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
! 810: IspVirt2Off(pcs, BIU_R2HSTSLO));
! 811: isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
! 812: if ((r2hisr & BIU_R2HST_INTR) == 0) {
! 813: *isrp = 0;
! 814: return (0);
! 815: }
! 816: switch (r2hisr & BIU_R2HST_ISTAT_MASK) {
! 817: case ISPR2HST_ROM_MBX_OK:
! 818: case ISPR2HST_ROM_MBX_FAIL:
! 819: case ISPR2HST_MBX_OK:
! 820: case ISPR2HST_MBX_FAIL:
! 821: case ISPR2HST_ASYNC_EVENT:
! 822: *isrp = r2hisr & 0xffff;
! 823: *mbox0p = (r2hisr >> 16);
! 824: *semap = 1;
! 825: return (1);
! 826: case ISPR2HST_RIO_16:
! 827: *isrp = r2hisr & 0xffff;
! 828: *mbox0p = ASYNC_RIO1;
! 829: *semap = 1;
! 830: return (1);
! 831: case ISPR2HST_FPOST:
! 832: *isrp = r2hisr & 0xffff;
! 833: *mbox0p = ASYNC_CMD_CMPLT;
! 834: *semap = 1;
! 835: return (1);
! 836: case ISPR2HST_FPOST_CTIO:
! 837: *isrp = r2hisr & 0xffff;
! 838: *mbox0p = ASYNC_CTIO_DONE;
! 839: *semap = 1;
! 840: return (1);
! 841: case ISPR2HST_RSPQ_UPDATE:
! 842: *isrp = r2hisr & 0xffff;
! 843: *mbox0p = 0;
! 844: *semap = 0;
! 845: return (1);
! 846: default:
! 847: return (0);
! 848: }
! 849: }
! 850: #endif
! 851:
! 852: static u_int16_t
! 853: isp_pci_rd_reg(struct ispsoftc *isp, int regoff)
! 854: {
! 855: u_int16_t rv;
! 856: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 857: int oldconf = 0;
! 858:
! 859: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
! 860: /*
! 861: * We will assume that someone has paused the RISC processor.
! 862: */
! 863: oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 864: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
! 865: oldconf | BIU_PCI_CONF1_SXP);
! 866: }
! 867: rv = BXR2(pcs, IspVirt2Off(isp, regoff));
! 868: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
! 869: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
! 870: }
! 871: return (rv);
! 872: }
! 873:
! 874: static void
! 875: isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
! 876: {
! 877: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 878: int oldconf = 0;
! 879:
! 880: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
! 881: /*
! 882: * We will assume that someone has paused the RISC processor.
! 883: */
! 884: oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 885: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
! 886: oldconf | BIU_PCI_CONF1_SXP);
! 887: }
! 888: BXW2(pcs, IspVirt2Off(isp, regoff), val);
! 889: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
! 890: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
! 891: }
! 892: }
! 893:
! 894: #if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT))
! 895: static u_int16_t
! 896: isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff)
! 897: {
! 898: u_int16_t rv, oc = 0;
! 899: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 900:
! 901: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
! 902: (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
! 903: u_int16_t tc;
! 904: /*
! 905: * We will assume that someone has paused the RISC processor.
! 906: */
! 907: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 908: tc = oc & ~BIU_PCI1080_CONF1_DMA;
! 909: if (regoff & SXP_BANK1_SELECT)
! 910: tc |= BIU_PCI1080_CONF1_SXP1;
! 911: else
! 912: tc |= BIU_PCI1080_CONF1_SXP0;
! 913: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
! 914: } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
! 915: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 916: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
! 917: oc | BIU_PCI1080_CONF1_DMA);
! 918: }
! 919: rv = BXR2(pcs, IspVirt2Off(isp, regoff));
! 920: if (oc) {
! 921: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
! 922: }
! 923: return (rv);
! 924: }
! 925:
! 926: static void
! 927: isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val)
! 928: {
! 929: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
! 930: int oc = 0;
! 931:
! 932: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
! 933: (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
! 934: u_int16_t tc;
! 935: /*
! 936: * We will assume that someone has paused the RISC processor.
! 937: */
! 938: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 939: tc = oc & ~BIU_PCI1080_CONF1_DMA;
! 940: if (regoff & SXP_BANK1_SELECT)
! 941: tc |= BIU_PCI1080_CONF1_SXP1;
! 942: else
! 943: tc |= BIU_PCI1080_CONF1_SXP0;
! 944: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
! 945: } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
! 946: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
! 947: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
! 948: oc | BIU_PCI1080_CONF1_DMA);
! 949: }
! 950: BXW2(pcs, IspVirt2Off(isp, regoff), val);
! 951: if (oc) {
! 952: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
! 953: }
! 954: }
! 955: #endif
! 956:
! 957: static int
! 958: isp_pci_mbxdma(struct ispsoftc *isp)
! 959: {
! 960: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
! 961: bus_dma_tag_t dmat = isp->isp_dmatag;
! 962: bus_dma_segment_t sg;
! 963: bus_size_t len;
! 964: fcparam *fcp;
! 965: int rs, i;
! 966:
! 967: if (isp->isp_rquest_dma) /* been here before? */
! 968: return (0);
! 969:
! 970: len = isp->isp_maxcmds * sizeof (XS_T *);
! 971: isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK);
! 972: if (isp->isp_xflist == NULL) {
! 973: isp_prt(isp, ISP_LOGERR, "cannot malloc xflist array");
! 974: return (1);
! 975: }
! 976: bzero(isp->isp_xflist, len);
! 977: len = isp->isp_maxcmds * sizeof (bus_dmamap_t);
! 978: pcs->pci_xfer_dmap = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
! 979: if (pcs->pci_xfer_dmap == NULL) {
! 980: free(isp->isp_xflist, M_DEVBUF);
! 981: isp->isp_xflist = NULL;
! 982: isp_prt(isp, ISP_LOGERR, "cannot malloc dma map array");
! 983: return (1);
! 984: }
! 985:
! 986: for (i = 0; i < isp->isp_maxcmds; i++) {
! 987: if (bus_dmamap_create(dmat, MAXPHYS, (MAXPHYS / NBPG) + 1,
! 988: MAXPHYS, 0, BUS_DMA_NOWAIT, &pcs->pci_xfer_dmap[i])) {
! 989: isp_prt(isp, ISP_LOGERR, "cannot create dma maps");
! 990: break;
! 991: }
! 992: }
! 993:
! 994: if (i < isp->isp_maxcmds) {
! 995: while (--i >= 0) {
! 996: bus_dmamap_destroy(dmat, pcs->pci_xfer_dmap[i]);
! 997: }
! 998: free(isp->isp_xflist, M_DEVBUF);
! 999: free(pcs->pci_xfer_dmap, M_DEVBUF);
! 1000: isp->isp_xflist = NULL;
! 1001: pcs->pci_xfer_dmap = NULL;
! 1002: return (1);
! 1003: }
! 1004:
! 1005: /*
! 1006: * Allocate and map the request queue.
! 1007: */
! 1008: len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
! 1009: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
! 1010: BUS_DMA_NOWAIT) ||
! 1011: bus_dmamem_map(isp->isp_dmatag, &sg, rs, len,
! 1012: (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
! 1013: goto dmafail;
! 1014: }
! 1015:
! 1016: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
! 1017: &isp->isp_rqdmap) || bus_dmamap_load(dmat, isp->isp_rqdmap,
! 1018: (caddr_t)isp->isp_rquest, len, NULL,
! 1019: BUS_DMA_NOWAIT)) {
! 1020: goto dmafail;
! 1021: }
! 1022: isp->isp_rquest_dma = isp->isp_rqdmap->dm_segs[0].ds_addr;
! 1023:
! 1024: /*
! 1025: * Allocate and map the result queue.
! 1026: */
! 1027: len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
! 1028: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
! 1029: BUS_DMA_NOWAIT) ||
! 1030: bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&isp->isp_result,
! 1031: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
! 1032: goto dmafail;
! 1033: }
! 1034: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
! 1035: &isp->isp_rsdmap) || bus_dmamap_load(isp->isp_dmatag,
! 1036: isp->isp_rsdmap, (caddr_t)isp->isp_result, len, NULL,
! 1037: BUS_DMA_NOWAIT)) {
! 1038: goto dmafail;
! 1039: }
! 1040: isp->isp_result_dma = isp->isp_rsdmap->dm_segs[0].ds_addr;
! 1041:
! 1042: if (IS_SCSI(isp)) {
! 1043: return (0);
! 1044: }
! 1045:
! 1046: fcp = isp->isp_param;
! 1047: len = ISP2100_SCRLEN;
! 1048: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
! 1049: BUS_DMA_NOWAIT) ||
! 1050: bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&fcp->isp_scratch,
! 1051: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
! 1052: goto dmafail;
! 1053: }
! 1054: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
! 1055: &isp->isp_scdmap) || bus_dmamap_load(dmat,
! 1056: isp->isp_scdmap, (caddr_t)fcp->isp_scratch, len, NULL,
! 1057: BUS_DMA_NOWAIT)) {
! 1058: goto dmafail;
! 1059: }
! 1060: fcp->isp_scdma = isp->isp_scdmap->dm_segs[0].ds_addr;
! 1061: return (0);
! 1062: dmafail:
! 1063: isp_prt(isp, ISP_LOGERR, "mailbox dma setup failure");
! 1064: for (i = 0; i < isp->isp_maxcmds; i++) {
! 1065: bus_dmamap_destroy(dmat, pcs->pci_xfer_dmap[i]);
! 1066: }
! 1067: free(isp->isp_xflist, M_DEVBUF);
! 1068: free(pcs->pci_xfer_dmap, M_DEVBUF);
! 1069: isp->isp_xflist = NULL;
! 1070: pcs->pci_xfer_dmap = NULL;
! 1071: return (1);
! 1072: }
! 1073:
! 1074: static int
! 1075: isp_pci_dmasetup(struct ispsoftc *isp, XS_T *xs, ispreq_t *rq,
! 1076: u_int16_t *nxtip, u_int16_t optr)
! 1077: {
! 1078: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
! 1079: bus_dmamap_t dmap;
! 1080: u_int16_t starti = isp->isp_reqidx, nxti = *nxtip;
! 1081: ispreq_t *qep;
! 1082: int segcnt, seg, error, ovseg, seglim, drq;
! 1083:
! 1084: qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, starti);
! 1085: dmap = pcs->pci_xfer_dmap[isp_handle_index(rq->req_handle)];
! 1086: if (xs->datalen == 0) {
! 1087: rq->req_seg_count = 1;
! 1088: goto mbxsync;
! 1089: }
! 1090:
! 1091: if (xs->flags & SCSI_DATA_IN) {
! 1092: drq = REQFLAG_DATA_IN;
! 1093: } else {
! 1094: drq = REQFLAG_DATA_OUT;
! 1095: }
! 1096:
! 1097: if (IS_FC(isp)) {
! 1098: seglim = ISP_RQDSEG_T2;
! 1099: ((ispreqt2_t *)rq)->req_totalcnt = xs->datalen;
! 1100: ((ispreqt2_t *)rq)->req_flags |= drq;
! 1101: } else {
! 1102: rq->req_flags |= drq;
! 1103: if (XS_CDBLEN(xs) > 12)
! 1104: seglim = 0;
! 1105: else
! 1106: seglim = ISP_RQDSEG;
! 1107: }
! 1108: error = bus_dmamap_load(isp->isp_dmatag, dmap, xs->data, xs->datalen,
! 1109: NULL, (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 1110: if (error) {
! 1111: XS_SETERR(xs, HBA_BOTCH);
! 1112: return (CMD_COMPLETE);
! 1113: }
! 1114:
! 1115: segcnt = dmap->dm_nsegs;
! 1116:
! 1117: isp_prt(isp, ISP_LOGDEBUG2, "%d byte %s %p in %d segs",
! 1118: xs->datalen, (xs->flags & SCSI_DATA_IN)? "read to" :
! 1119: "write from", xs->data, segcnt);
! 1120:
! 1121: for (seg = 0, rq->req_seg_count = 0;
! 1122: seg < segcnt && rq->req_seg_count < seglim;
! 1123: seg++, rq->req_seg_count++) {
! 1124: if (isp->isp_type & ISP_HA_FC) {
! 1125: ispreqt2_t *rq2 = (ispreqt2_t *)rq;
! 1126: rq2->req_dataseg[rq2->req_seg_count].ds_count =
! 1127: dmap->dm_segs[seg].ds_len;
! 1128: rq2->req_dataseg[rq2->req_seg_count].ds_base =
! 1129: dmap->dm_segs[seg].ds_addr;
! 1130: } else {
! 1131: rq->req_dataseg[rq->req_seg_count].ds_count =
! 1132: dmap->dm_segs[seg].ds_len;
! 1133: rq->req_dataseg[rq->req_seg_count].ds_base =
! 1134: dmap->dm_segs[seg].ds_addr;
! 1135: }
! 1136: isp_prt(isp, ISP_LOGDEBUG2, "seg0.[%d]={0x%lx,%lu}",
! 1137: rq->req_seg_count, (long) dmap->dm_segs[seg].ds_addr,
! 1138: (unsigned long) dmap->dm_segs[seg].ds_len);
! 1139: }
! 1140:
! 1141: if (seg == segcnt) {
! 1142: goto dmasync;
! 1143: }
! 1144:
! 1145: do {
! 1146: u_int16_t onxti;
! 1147: ispcontreq_t *crq, *cqe, local;
! 1148:
! 1149: crq = &local;
! 1150:
! 1151: cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
! 1152: onxti = nxti;
! 1153: nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
! 1154: if (nxti == optr) {
! 1155: isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
! 1156: bus_dmamap_unload(isp->isp_dmatag, dmap);
! 1157: XS_SETERR(xs, HBA_BOTCH);
! 1158: return (CMD_EAGAIN);
! 1159: }
! 1160: rq->req_header.rqs_entry_count++;
! 1161: bzero((void *)crq, sizeof (*crq));
! 1162: crq->req_header.rqs_entry_count = 1;
! 1163: crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
! 1164:
! 1165: for (ovseg = 0; seg < segcnt && ovseg < ISP_CDSEG;
! 1166: rq->req_seg_count++, seg++, ovseg++) {
! 1167: crq->req_dataseg[ovseg].ds_count =
! 1168: dmap->dm_segs[seg].ds_len;
! 1169: crq->req_dataseg[ovseg].ds_base =
! 1170: dmap->dm_segs[seg].ds_addr;
! 1171: isp_prt(isp, ISP_LOGDEBUG2, "seg%d.[%d]={0x%lx,%lu}",
! 1172: rq->req_header.rqs_entry_count - 1,
! 1173: rq->req_seg_count, (long)dmap->dm_segs[seg].ds_addr,
! 1174: (unsigned long) dmap->dm_segs[seg].ds_len);
! 1175: }
! 1176: isp_put_cont_req(isp, crq, cqe);
! 1177: MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
! 1178: } while (seg < segcnt);
! 1179:
! 1180: dmasync:
! 1181: bus_dmamap_sync(isp->isp_dmatag, dmap, 0, dmap->dm_mapsize,
! 1182: (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
! 1183: BUS_DMASYNC_PREWRITE);
! 1184:
! 1185: mbxsync:
! 1186: switch (rq->req_header.rqs_entry_type) {
! 1187: case RQSTYPE_REQUEST:
! 1188: isp_put_request(isp, rq, qep);
! 1189: break;
! 1190: case RQSTYPE_CMDONLY:
! 1191: isp_put_extended_request(isp, (ispextreq_t *)rq,
! 1192: (ispextreq_t *)qep);
! 1193: break;
! 1194: case RQSTYPE_T2RQS:
! 1195: isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) qep);
! 1196: break;
! 1197: }
! 1198: *nxtip = nxti;
! 1199: return (CMD_QUEUED);
! 1200: }
! 1201:
! 1202: static int
! 1203: isp_pci_intr(void *arg)
! 1204: {
! 1205: u_int16_t isr, sema, mbox;
! 1206: struct ispsoftc *isp = (struct ispsoftc *)arg;
! 1207:
! 1208: isp->isp_intcnt++;
! 1209: if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
! 1210: isp->isp_intbogus++;
! 1211: return (0);
! 1212: } else {
! 1213: isp->isp_osinfo.onintstack = 1;
! 1214: isp_intr(isp, isr, sema, mbox);
! 1215: isp->isp_osinfo.onintstack = 0;
! 1216: return (1);
! 1217: }
! 1218: }
! 1219:
! 1220: static void
! 1221: isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle)
! 1222: {
! 1223: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
! 1224: bus_dmamap_t dmap = pcs->pci_xfer_dmap[isp_handle_index(handle)];
! 1225: bus_dmamap_sync(isp->isp_dmatag, dmap, 0, dmap->dm_mapsize,
! 1226: (xs->flags & SCSI_DATA_IN)?
! 1227: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
! 1228: bus_dmamap_unload(isp->isp_dmatag, dmap);
! 1229: }
! 1230:
! 1231: static void
! 1232: isp_pci_reset1(struct ispsoftc *isp)
! 1233: {
! 1234: /* Make sure the BIOS is disabled */
! 1235: isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
! 1236: if (isp->isp_osinfo.no_mbox_ints == 0) {
! 1237: ENABLE_INTS(isp);
! 1238: }
! 1239: }
! 1240:
! 1241: static void
! 1242: isp_pci_dumpregs(struct ispsoftc *isp, const char *msg)
! 1243: {
! 1244: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
! 1245: if (msg)
! 1246: isp_prt(isp, ISP_LOGERR, "%s", msg);
! 1247: isp_prt(isp, ISP_LOGERR, "PCI Status Command/Status=%x\n",
! 1248: pci_conf_read(pcs->pci_pc, pcs->pci_tag, PCI_COMMAND_STATUS_REG));
! 1249: }
CVSweb