1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1997-2006 by Matthew Jacob 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice immediately at the beginning of the file, without modification, 12 * this list of conditions, and the following disclaimer. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/* 29 * SBus specific probe and attach routines for Qlogic ISP SCSI adapters. 30 * FreeBSD Version. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD$"); 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/linker.h> 39#include <sys/firmware.h> 40#include <sys/bus.h> 41#include <sys/kernel.h> 42#include <sys/module.h> 43#include <sys/resource.h> 44 45#include <dev/ofw/ofw_bus.h> 46#include <dev/ofw/openfirm.h> 47 48#include <machine/bus.h> 49#include <machine/ofw_machdep.h> 50#include <machine/resource.h> 51#include <sys/rman.h> 52#include <sparc64/sbus/sbusvar.h> 53 54#include <dev/isp/isp_freebsd.h> 55 56static uint32_t isp_sbus_rd_reg(ispsoftc_t *, int); 57static void isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t); 58static void isp_sbus_run_isr(ispsoftc_t *); 59static int isp_sbus_mbxdma(ispsoftc_t *); 60static void isp_sbus_mbxdmafree(ispsoftc_t *); 61static int isp_sbus_dmasetup(ispsoftc_t *, XS_T *, void *); 62static void isp_sbus_dumpregs(ispsoftc_t *, const char *); 63 64static struct ispmdvec mdvec = { 65 isp_sbus_run_isr, 66 isp_sbus_rd_reg, 67 isp_sbus_wr_reg, 68 isp_sbus_mbxdma, 69 isp_sbus_dmasetup, 70 isp_common_dmateardown, 71 NULL, 72 isp_sbus_dumpregs, 73 NULL, 74 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 75}; 76 77static int isp_sbus_probe (device_t); 78static int isp_sbus_attach (device_t); 79static int isp_sbus_detach (device_t); 80 81 82#define ISP_SBD(isp) ((struct isp_sbussoftc *)isp)->sbus_dev 83struct isp_sbussoftc { 84 ispsoftc_t sbus_isp; 85 device_t sbus_dev; 86 struct resource * regs; 87 void * irq; 88 int iqd; 89 int rgd; 90 void * ih; 91 int16_t sbus_poff[_NREG_BLKS]; 92 sdparam sbus_param; 93 struct isp_spi sbus_spi; 94 struct ispmdvec sbus_mdvec; 95}; 96 97 98static device_method_t isp_sbus_methods[] = { 99 /* Device interface */ 100 DEVMETHOD(device_probe, isp_sbus_probe), 101 DEVMETHOD(device_attach, isp_sbus_attach), 102 DEVMETHOD(device_detach, isp_sbus_detach), 103 { 0, 0 } 104}; 105 106static driver_t isp_sbus_driver = { 107 "isp", isp_sbus_methods, sizeof (struct isp_sbussoftc) 108}; 109static devclass_t isp_devclass; 110DRIVER_MODULE(isp, sbus, isp_sbus_driver, isp_devclass, 0, 0); 111MODULE_DEPEND(isp, cam, 1, 1, 1); 112MODULE_DEPEND(isp, firmware, 1, 1, 1); 113 114static int 115isp_sbus_probe(device_t dev) 116{ 117 int found = 0; 118 const char *name = ofw_bus_get_name(dev); 119 if (strcmp(name, "SUNW,isp") == 0 || 120 strcmp(name, "QLGC,isp") == 0 || 121 strcmp(name, "ptisp") == 0 || 122 strcmp(name, "PTI,ptisp") == 0) { 123 found++; 124 } 125 if (!found) 126 return (ENXIO); 127 128 if (isp_announced == 0 && bootverbose) { 129 printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 130 "Core Version %d.%d\n", 131 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 132 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 133 isp_announced++; 134 } 135 return (0); 136} 137 138static int 139isp_sbus_attach(device_t dev) 140{ 141 struct isp_sbussoftc *sbs = device_get_softc(dev); 142 ispsoftc_t *isp = &sbs->sbus_isp; 143 int tval, isp_debug, role, ispburst, default_id; 144 145 sbs->sbus_dev = dev; 146 sbs->sbus_mdvec = mdvec; 147 isp->isp_dev = dev; 148 mtx_init(&isp->isp_lock, "isp", NULL, MTX_DEF); 149 150 role = 0; 151 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 152 "role", &role) == 0 && 153 ((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) { 154 device_printf(dev, "setting role to 0x%x\n", role); 155 } else { 156 role = ISP_DEFAULT_ROLES; 157 } 158 159 sbs->irq = sbs->regs = NULL; 160 sbs->rgd = sbs->iqd = 0; 161 162 sbs->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sbs->rgd, 163 RF_ACTIVE); 164 if (sbs->regs == NULL) { 165 device_printf(dev, "unable to map registers\n"); 166 goto bad; 167 } 168 169 sbs->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 170 sbs->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF; 171 sbs->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF; 172 sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF; 173 sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 174 isp->isp_regs = sbs->regs; 175 isp->isp_mdvec = &sbs->sbus_mdvec; 176 isp->isp_bustype = ISP_BT_SBUS; 177 isp->isp_type = ISP_HA_SCSI_UNKNOWN; 178 isp->isp_param = &sbs->sbus_param; 179 isp->isp_osinfo.pc.ptr = &sbs->sbus_spi; 180 isp->isp_revision = 0; /* XXX */ 181 isp->isp_nchan = 1; 182 if (IS_FC(isp)) 183 ISP_FC_PC(isp, 0)->def_role = role; 184 185 /* 186 * Get the clock frequency and convert it from HZ to MHz, 187 * rounding up. This defaults to 25MHz if there isn't a 188 * device specific one in the OFW device tree. 189 */ 190 sbs->sbus_mdvec.dv_clock = (sbus_get_clockfreq(dev) + 500000)/1000000; 191 192 /* 193 * Now figure out what the proper burst sizes, etc., to use. 194 * Unfortunately, there is no ddi_dma_burstsizes here which 195 * walks up the tree finding the limiting burst size node (if 196 * any). We just use what's here for isp. 197 */ 198 ispburst = sbus_get_burstsz(dev); 199 if (ispburst == 0) { 200 ispburst = SBUS_BURST_32 - 1; 201 } 202 sbs->sbus_mdvec.dv_conf1 = 0; 203 if (ispburst & (1 << 5)) { 204 sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_32; 205 } else if (ispburst & (1 << 4)) { 206 sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_16; 207 } else if (ispburst & (1 << 3)) { 208 sbs->sbus_mdvec.dv_conf1 = 209 BIU_SBUS_CONF1_BURST8 | BIU_SBUS_CONF1_FIFO_8; 210 } 211 if (sbs->sbus_mdvec.dv_conf1) { 212 sbs->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE; 213 } 214 215 /* 216 * We don't trust NVRAM on SBus cards 217 */ 218 isp->isp_confopts |= ISP_CFG_NONVRAM; 219 220 /* 221 * Mark things if we're a PTI SBus adapter. 222 */ 223 if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 || 224 strcmp("ptisp", ofw_bus_get_name(dev)) == 0) { 225 SDPARAM(isp, 0)->isp_ptisp = 1; 226 } 227 228 isp->isp_osinfo.fw = firmware_get("isp_1000"); 229 if (isp->isp_osinfo.fw) { 230 union { 231 const void *cp; 232 uint16_t *sp; 233 } stupid; 234 stupid.cp = isp->isp_osinfo.fw->data; 235 isp->isp_mdvec->dv_ispfw = stupid.sp; 236 } 237 238 tval = 0; 239 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 240 "fwload_disable", &tval) == 0 && tval != 0) { 241 isp->isp_confopts |= ISP_CFG_NORELOAD; 242 } 243 244 default_id = -1; 245 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 246 "iid", &tval) == 0) { 247 default_id = tval; 248 isp->isp_confopts |= ISP_CFG_OWNLOOPID; 249 } 250 if (default_id == -1) { 251 default_id = OF_getscsinitid(dev); 252 } 253 ISP_SPI_PC(isp, 0)->iid = default_id; 254 255 isp_debug = 0; 256 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 257 "debug", &isp_debug); 258 259 sbs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sbs->iqd, 260 RF_ACTIVE | RF_SHAREABLE); 261 if (sbs->irq == NULL) { 262 device_printf(dev, "could not allocate interrupt\n"); 263 goto bad; 264 } 265 266 if (bus_setup_intr(dev, sbs->irq, ISP_IFLAGS, NULL, isp_platform_intr, 267 isp, &sbs->ih)) { 268 device_printf(dev, "could not setup interrupt\n"); 269 (void) bus_release_resource(dev, SYS_RES_IRQ, 270 sbs->iqd, sbs->irq); 271 goto bad; 272 } 273 isp->isp_nirq = 1; 274 275 /* 276 * Set up logging levels. 277 */ 278 if (isp_debug) { 279 isp->isp_dblev = isp_debug; 280 } else { 281 isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 282 } 283 if (bootverbose) { 284 isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 285 } 286 287 /* 288 * Make sure we're in reset state. 289 */ 290 ISP_LOCK(isp); 291 if (isp_reinit(isp, 1) != 0) { 292 ISP_UNLOCK(isp); 293 goto bad; 294 } 295 ISP_UNLOCK(isp); 296 if (isp_attach(isp)) { 297 ISP_LOCK(isp); 298 isp_shutdown(isp); 299 ISP_UNLOCK(isp); 300 goto bad; 301 } 302 return (0); 303 304bad: 305 if (isp->isp_nirq > 0) { 306 (void) bus_teardown_intr(dev, sbs->irq, sbs->ih); 307 (void) bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, 308 sbs->irq); 309 } 310 311 if (sbs->regs) { 312 (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd, 313 sbs->regs); 314 } 315 mtx_destroy(&isp->isp_lock); 316 return (ENXIO); 317} 318 319static int 320isp_sbus_detach(device_t dev) 321{ 322 struct isp_sbussoftc *sbs = device_get_softc(dev); 323 ispsoftc_t *isp = &sbs->sbus_isp; 324 int status; 325 326 status = isp_detach(isp); 327 if (status) 328 return (status); 329 ISP_LOCK(isp); 330 isp_shutdown(isp); 331 ISP_UNLOCK(isp); 332 if (isp->isp_nirq > 0) { 333 (void) bus_teardown_intr(dev, sbs->irq, sbs->ih); 334 (void) bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, 335 sbs->irq); 336 } 337 (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd, sbs->regs); 338 isp_sbus_mbxdmafree(isp); 339 mtx_destroy(&isp->isp_lock); 340 return (0); 341} 342 343#define IspVirt2Off(a, x) \ 344 (((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \ 345 _BLK_REG_SHFT] + ((x) & 0xff)) 346 347#define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off)) 348 349static void 350isp_sbus_run_isr(ispsoftc_t *isp) 351{ 352 uint16_t isr, sema, info; 353 354 isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR)); 355 sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA)); 356 isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 357 isr &= INT_PENDING_MASK(isp); 358 sema &= BIU_SEMA_LOCK; 359 if (isr == 0 && sema == 0) 360 return; 361 if (sema != 0) { 362 info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 363 if (info & MBOX_COMMAND_COMPLETE) 364 isp_intr_mbox(isp, info); 365 else 366 isp_intr_async(isp, info); 367 if (isp->isp_state == ISP_RUNSTATE) 368 isp_intr_respq(isp); 369 } else 370 isp_intr_respq(isp); 371 ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); 372 if (sema) 373 ISP_WRITE(isp, BIU_SEMA, 0); 374} 375 376static uint32_t 377isp_sbus_rd_reg(ispsoftc_t *isp, int regoff) 378{ 379 uint16_t rval; 380 struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp; 381 int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 382 offset += (regoff & 0xff); 383 rval = BXR2(isp, offset); 384 isp_prt(isp, ISP_LOGDEBUG3, 385 "isp_sbus_rd_reg(off %x) = %x", regoff, rval); 386 return (rval); 387} 388 389static void 390isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 391{ 392 struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp; 393 int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 394 offset += (regoff & 0xff); 395 isp_prt(isp, ISP_LOGDEBUG3, 396 "isp_sbus_wr_reg(off %x) = %x", regoff, val); 397 bus_write_2(isp->isp_regs, offset, val); 398 MEMORYBARRIER(isp, SYNC_REG, offset, 2, -1); 399} 400 401struct imush { 402 bus_addr_t maddr; 403 int error; 404}; 405 406static void imc(void *, bus_dma_segment_t *, int, int); 407 408static void 409imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 410{ 411 struct imush *imushp = (struct imush *) arg; 412 413 if (!(imushp->error = error)) 414 imushp->maddr = segs[0].ds_addr; 415} 416 417static int 418isp_sbus_mbxdma(ispsoftc_t *isp) 419{ 420 caddr_t base; 421 uint32_t len; 422 int i, error; 423 struct imush im; 424 425 /* Already been here? If so, leave... */ 426 if (isp->isp_xflist != NULL) 427 return (0); 428 if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0) 429 return (0); 430 ISP_UNLOCK(isp); 431 if (isp->isp_rquest != NULL) 432 goto gotmaxcmds; 433 434 if (bus_dma_tag_create(bus_get_dma_tag(ISP_SBD(isp)), 1, 435 BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT, 436 BUS_SPACE_MAXADDR_32BIT, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 437 ISP_NSEG_MAX, BUS_SPACE_MAXADDR_24BIT, 0, 438 busdma_lock_mutex, &isp->isp_lock, &isp->isp_osinfo.dmat)) { 439 isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 440 goto bad; 441 } 442 443 /* 444 * Allocate and map the request queue. 445 */ 446 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 447 if (bus_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, BUS_SPACE_MAXADDR_24BIT+1, 448 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 449 len, 1, len, 0, busdma_lock_mutex, &isp->isp_lock, 450 &isp->isp_osinfo.reqdmat)) { 451 isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); 452 goto bad; 453 } 454 if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, 455 BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { 456 isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); 457 bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 458 goto bad; 459 } 460 isp->isp_rquest = base; 461 im.error = 0; 462 if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, 463 base, len, imc, &im, 0) || im.error) { 464 isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); 465 goto bad; 466 } 467 isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", 468 (uintmax_t)im.maddr, (uintmax_t)len); 469 isp->isp_rquest_dma = im.maddr; 470 471 /* 472 * Allocate and map the result queue. 473 */ 474 len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 475 if (bus_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, BUS_SPACE_MAXADDR_24BIT+1, 476 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 477 len, 1, len, 0, busdma_lock_mutex, &isp->isp_lock, 478 &isp->isp_osinfo.respdmat)) { 479 isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); 480 goto bad; 481 } 482 if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, 483 BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { 484 isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); 485 bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 486 goto bad; 487 } 488 isp->isp_result = base; 489 im.error = 0; 490 if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, 491 base, len, imc, &im, 0) || im.error) { 492 isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); 493 goto bad; 494 } 495 isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", 496 (uintmax_t)im.maddr, (uintmax_t)len); 497 isp->isp_result_dma = im.maddr; 498 499 if (isp->isp_maxcmds == 0) { 500 ISP_LOCK(isp); 501 return (0); 502 } 503 504gotmaxcmds: 505 len = sizeof (struct isp_pcmd) * isp->isp_maxcmds; 506 isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) 507 malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 508 for (i = 0; i < isp->isp_maxcmds; i++) { 509 struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 510 error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 511 if (error) { 512 isp_prt(isp, ISP_LOGERR, 513 "error %d creating per-cmd DMA maps", error); 514 while (--i >= 0) { 515 bus_dmamap_destroy(isp->isp_osinfo.dmat, 516 isp->isp_osinfo.pcmd_pool[i].dmap); 517 } 518 goto bad; 519 } 520 callout_init_mtx(&pcmd->wdog, &isp->isp_lock, 0); 521 if (i == isp->isp_maxcmds-1) { 522 pcmd->next = NULL; 523 } else { 524 pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 525 } 526 } 527 isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 528 529 len = sizeof (isp_hdl_t *) * isp->isp_maxcmds; 530 isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 531 for (len = 0; len < isp->isp_maxcmds - 1; len++) 532 isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 533 isp->isp_xffree = isp->isp_xflist; 534 535 ISP_LOCK(isp); 536 return (0); 537 538bad: 539 isp_sbus_mbxdmafree(isp); 540 ISP_LOCK(isp); 541 return (1); 542} 543 544static void 545isp_sbus_mbxdmafree(ispsoftc_t *isp) 546{ 547 int i; 548 549 if (isp->isp_xflist != NULL) { 550 free(isp->isp_xflist, M_DEVBUF); 551 isp->isp_xflist = NULL; 552 } 553 if (isp->isp_osinfo.pcmd_pool != NULL) { 554 for (i = 0; i < isp->isp_maxcmds; i++) { 555 bus_dmamap_destroy(isp->isp_osinfo.dmat, 556 isp->isp_osinfo.pcmd_pool[i].dmap); 557 } 558 free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 559 isp->isp_osinfo.pcmd_pool = NULL; 560 } 561 if (isp->isp_result_dma != 0) { 562 bus_dmamap_unload(isp->isp_osinfo.respdmat, 563 isp->isp_osinfo.respmap); 564 isp->isp_result_dma = 0; 565 } 566 if (isp->isp_result != NULL) { 567 bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, 568 isp->isp_osinfo.respmap); 569 bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 570 isp->isp_result = NULL; 571 } 572 if (isp->isp_rquest_dma != 0) { 573 bus_dmamap_unload(isp->isp_osinfo.reqdmat, 574 isp->isp_osinfo.reqmap); 575 isp->isp_rquest_dma = 0; 576 } 577 if (isp->isp_rquest != NULL) { 578 bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, 579 isp->isp_osinfo.reqmap); 580 bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 581 isp->isp_rquest = NULL; 582 } 583} 584 585typedef struct { 586 ispsoftc_t *isp; 587 void *cmd_token; 588 void *rq; /* original request */ 589 int error; 590} mush_t; 591 592#define MUSHERR_NOQENTRIES -2 593 594static void 595dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 596{ 597 mush_t *mp = (mush_t *) arg; 598 ispsoftc_t *isp = mp->isp; 599 struct ccb_scsiio *csio = mp->cmd_token; 600 isp_ddir_t ddir; 601 int sdir; 602 603 if (error) { 604 mp->error = error; 605 return; 606 } 607 if (nseg == 0) { 608 ddir = ISP_NOXFR; 609 } else { 610 if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 611 ddir = ISP_FROM_DEVICE; 612 } else { 613 ddir = ISP_TO_DEVICE; 614 } 615 if ((csio->ccb_h.func_code == XPT_CONT_TARGET_IO) ^ 616 ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)) { 617 sdir = BUS_DMASYNC_PREREAD; 618 } else { 619 sdir = BUS_DMASYNC_PREWRITE; 620 } 621 bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, 622 sdir); 623 } 624 625 if (isp_send_cmd(isp, mp->rq, dm_segs, nseg, XS_XFRLEN(csio), 626 ddir, NULL) != CMD_QUEUED) { 627 mp->error = MUSHERR_NOQENTRIES; 628 } 629} 630 631static int 632isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 633{ 634 mush_t mush, *mp; 635 int error; 636 637 mp = &mush; 638 mp->isp = isp; 639 mp->cmd_token = csio; 640 mp->rq = ff; 641 mp->error = 0; 642 643 error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, 644 PISP_PCMD(csio)->dmap, (union ccb *)csio, dma2, mp, 0); 645 if (error == EINPROGRESS) { 646 bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 647 mp->error = EINVAL; 648 isp_prt(isp, ISP_LOGERR, 649 "deferred dma allocation not supported"); 650 } else if (error && mp->error == 0) { 651#ifdef DIAGNOSTIC 652 isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 653#endif 654 mp->error = error; 655 } 656 if (mp->error) { 657 int retval = CMD_COMPLETE; 658 if (mp->error == MUSHERR_NOQENTRIES) { 659 retval = CMD_EAGAIN; 660 } else if (mp->error == EFBIG) { 661 XS_SETERR(csio, CAM_REQ_TOO_BIG); 662 } else if (mp->error == EINVAL) { 663 XS_SETERR(csio, CAM_REQ_INVALID); 664 } else { 665 XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 666 } 667 return (retval); 668 } 669 return (CMD_QUEUED); 670} 671 672static void 673isp_sbus_dumpregs(ispsoftc_t *isp, const char *msg) 674{ 675 if (msg) 676 printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 677 else 678 printf("%s:\n", device_get_nameunit(isp->isp_dev)); 679 printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 680 printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 681 ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 682 printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 683 684 685 ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 686 printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 687 ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 688 ISP_READ(isp, CDMA_FIFO_STS)); 689 printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 690 ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 691 ISP_READ(isp, DDMA_FIFO_STS)); 692 printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 693 ISP_READ(isp, SXP_INTERRUPT), 694 ISP_READ(isp, SXP_GROSS_ERR), 695 ISP_READ(isp, SXP_PINS_CTRL)); 696 ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 697 printf(" mbox regs: %x %x %x %x %x\n", 698 ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 699 ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 700 ISP_READ(isp, OUTMAILBOX4)); 701} 702