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