1 /* $OpenBSD: ciss.c,v 1.92 2024/04/14 03:26:25 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2005,2006 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "bio.h" 21 22 /* #define CISS_DEBUG */ 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/buf.h> 27 #include <sys/ioctl.h> 28 #include <sys/device.h> 29 #include <sys/kernel.h> 30 #include <sys/malloc.h> 31 32 #include <machine/bus.h> 33 34 #include <scsi/scsi_all.h> 35 #include <scsi/scsiconf.h> 36 37 #include <dev/ic/cissreg.h> 38 #include <dev/ic/cissvar.h> 39 40 #if NBIO > 0 41 #include <dev/biovar.h> 42 #endif 43 #include <sys/sensors.h> 44 45 #ifdef CISS_DEBUG 46 #define CISS_DPRINTF(m,a) if (ciss_debug & (m)) printf a 47 #define CISS_D_CMD 0x0001 48 #define CISS_D_INTR 0x0002 49 #define CISS_D_MISC 0x0004 50 #define CISS_D_DMA 0x0008 51 #define CISS_D_IOCTL 0x0010 52 #define CISS_D_ERR 0x0020 53 int ciss_debug = 0 54 /* | CISS_D_CMD */ 55 /* | CISS_D_INTR */ 56 /* | CISS_D_MISC */ 57 /* | CISS_D_DMA */ 58 /* | CISS_D_IOCTL */ 59 /* | CISS_D_ERR */ 60 ; 61 #else 62 #define CISS_DPRINTF(m,a) /* m, a */ 63 #endif 64 65 struct cfdriver ciss_cd = { 66 NULL, "ciss", DV_DULL 67 }; 68 69 void ciss_scsi_cmd(struct scsi_xfer *xs); 70 int ciss_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int); 71 72 const struct scsi_adapter ciss_switch = { 73 ciss_scsi_cmd, NULL, NULL, NULL, ciss_scsi_ioctl 74 }; 75 76 #if NBIO > 0 77 int ciss_ioctl(struct device *, u_long, caddr_t); 78 #endif 79 int ciss_sync(struct ciss_softc *sc); 80 void ciss_heartbeat(void *v); 81 #ifndef SMALL_KERNEL 82 void ciss_sensors(void *); 83 #endif 84 85 void * ciss_get_ccb(void *); 86 void ciss_put_ccb(void *, void *); 87 int ciss_cmd(struct ciss_ccb *ccb, int flags, int wait); 88 int ciss_done(struct ciss_ccb *ccb); 89 int ciss_error(struct ciss_ccb *ccb); 90 91 struct ciss_ld *ciss_pdscan(struct ciss_softc *sc, int ld); 92 int ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq); 93 int ciss_ldmap(struct ciss_softc *sc); 94 int ciss_ldid(struct ciss_softc *, int, struct ciss_ldid *); 95 int ciss_ldstat(struct ciss_softc *, int, struct ciss_ldstat *); 96 int ciss_pdid(struct ciss_softc *, u_int8_t, struct ciss_pdid *, int); 97 int ciss_blink(struct ciss_softc *, int, int, int, struct ciss_blink *); 98 99 void * 100 ciss_get_ccb(void *xsc) 101 { 102 struct ciss_softc *sc = xsc; 103 struct ciss_ccb *ccb; 104 105 mtx_enter(&sc->sc_free_ccb_mtx); 106 ccb = SLIST_FIRST(&sc->sc_free_ccb); 107 if (ccb != NULL) { 108 SLIST_REMOVE_HEAD(&sc->sc_free_ccb, ccb_link); 109 ccb->ccb_state = CISS_CCB_READY; 110 ccb->ccb_xs = NULL; 111 } 112 mtx_leave(&sc->sc_free_ccb_mtx); 113 114 return (ccb); 115 } 116 117 void 118 ciss_put_ccb(void *xsc, void *xccb) 119 { 120 struct ciss_softc *sc = xsc; 121 struct ciss_ccb *ccb = xccb; 122 123 ccb->ccb_state = CISS_CCB_FREE; 124 ccb->ccb_xs = NULL; 125 ccb->ccb_data = NULL; 126 127 mtx_enter(&sc->sc_free_ccb_mtx); 128 SLIST_INSERT_HEAD(&sc->sc_free_ccb, ccb, ccb_link); 129 mtx_leave(&sc->sc_free_ccb_mtx); 130 } 131 132 int 133 ciss_attach(struct ciss_softc *sc) 134 { 135 struct scsibus_attach_args saa; 136 struct scsibus_softc *scsibus; 137 struct ciss_ccb *ccb; 138 struct ciss_cmd *cmd; 139 struct ciss_inquiry *inq; 140 bus_dma_segment_t seg[1]; 141 int error, i, total, rseg, maxfer; 142 ciss_lock_t lock; 143 paddr_t pa; 144 145 bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff, 146 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 147 148 if (sc->cfg.signature != CISS_SIGNATURE) { 149 printf(": bad sign 0x%08x\n", sc->cfg.signature); 150 return -1; 151 } 152 153 if (!(sc->cfg.methods & CISS_METH_SIMPL)) { 154 printf(": not simple 0x%08x\n", sc->cfg.methods); 155 return -1; 156 } 157 158 sc->cfg.rmethod = CISS_METH_SIMPL; 159 sc->cfg.paddr_lim = 0; /* 32bit addrs */ 160 sc->cfg.int_delay = 0; /* disable coalescing */ 161 sc->cfg.int_count = 0; 162 strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname)); 163 sc->cfg.driverf |= CISS_DRV_PRF; /* enable prefetch */ 164 if (!sc->cfg.maxsg) 165 sc->cfg.maxsg = MAXPHYS / PAGE_SIZE; 166 167 bus_space_write_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff, 168 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 169 bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg), 170 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); 171 172 bus_space_write_4(sc->iot, sc->ioh, CISS_IDB, CISS_IDB_CFG); 173 bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4, 174 BUS_SPACE_BARRIER_WRITE); 175 for (i = 1000; i--; DELAY(1000)) { 176 /* XXX maybe IDB is really 64bit? - hp dl380 needs this */ 177 (void)bus_space_read_4(sc->iot, sc->ioh, CISS_IDB + 4); 178 if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG)) 179 break; 180 bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4, 181 BUS_SPACE_BARRIER_READ); 182 } 183 184 if (bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG) { 185 printf(": cannot set config\n"); 186 return -1; 187 } 188 189 bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff, 190 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 191 192 if (!(sc->cfg.amethod & CISS_METH_SIMPL)) { 193 printf(": cannot simplify 0x%08x\n", sc->cfg.amethod); 194 return -1; 195 } 196 197 /* i'm ready for you and i hope you're ready for me */ 198 for (i = 30000; i--; DELAY(1000)) { 199 if (bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff + 200 offsetof(struct ciss_config, amethod)) & CISS_METH_READY) 201 break; 202 bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff + 203 offsetof(struct ciss_config, amethod), 4, 204 BUS_SPACE_BARRIER_READ); 205 } 206 207 if (!(bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff + 208 offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) { 209 printf(": she never came ready for me 0x%08x\n", 210 sc->cfg.amethod); 211 return -1; 212 } 213 214 sc->maxcmd = sc->cfg.maxcmd; 215 sc->maxsg = sc->cfg.maxsg; 216 if (sc->maxsg > MAXPHYS / PAGE_SIZE) 217 sc->maxsg = MAXPHYS / PAGE_SIZE; 218 i = sizeof(struct ciss_ccb) + 219 sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1); 220 for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1) 221 ; 222 223 total = sc->ccblen * sc->maxcmd; 224 if ((error = bus_dmamem_alloc(sc->dmat, total, PAGE_SIZE, 0, 225 sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO))) { 226 printf(": cannot allocate CCBs (%d)\n", error); 227 return -1; 228 } 229 230 if ((error = bus_dmamem_map(sc->dmat, sc->cmdseg, rseg, total, 231 (caddr_t *)&sc->ccbs, BUS_DMA_NOWAIT))) { 232 printf(": cannot map CCBs (%d)\n", error); 233 return -1; 234 } 235 236 if ((error = bus_dmamap_create(sc->dmat, total, 1, 237 total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) { 238 printf(": cannot create CCBs dmamap (%d)\n", error); 239 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 240 return -1; 241 } 242 243 if ((error = bus_dmamap_load(sc->dmat, sc->cmdmap, sc->ccbs, total, 244 NULL, BUS_DMA_NOWAIT))) { 245 printf(": cannot load CCBs dmamap (%d)\n", error); 246 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 247 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 248 return -1; 249 } 250 251 SLIST_INIT(&sc->sc_free_ccb); 252 mtx_init(&sc->sc_free_ccb_mtx, IPL_BIO); 253 254 maxfer = sc->maxsg * PAGE_SIZE; 255 for (i = 0; total; i++, total -= sc->ccblen) { 256 ccb = sc->ccbs + i * sc->ccblen; 257 cmd = &ccb->ccb_cmd; 258 pa = sc->cmdseg[0].ds_addr + i * sc->ccblen; 259 260 ccb->ccb_sc = sc; 261 ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd); 262 ccb->ccb_state = CISS_CCB_FREE; 263 264 cmd->id = htole32(i << 2); 265 cmd->id_hi = htole32(0); 266 cmd->sgin = sc->maxsg; 267 cmd->sglen = htole16((u_int16_t)cmd->sgin); 268 cmd->err_len = htole32(sizeof(ccb->ccb_err)); 269 pa += offsetof(struct ciss_ccb, ccb_err); 270 cmd->err_pa = htole64((u_int64_t)pa); 271 272 if ((error = bus_dmamap_create(sc->dmat, maxfer, sc->maxsg, 273 maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 274 &ccb->ccb_dmamap))) 275 break; 276 277 SLIST_INSERT_HEAD(&sc->sc_free_ccb, ccb, ccb_link); 278 } 279 280 scsi_iopool_init(&sc->sc_iopool, sc, ciss_get_ccb, ciss_put_ccb); 281 282 if (i < sc->maxcmd) { 283 printf(": cannot create ccb#%d dmamap (%d)\n", i, error); 284 if (i == 0) { 285 /* TODO leaking cmd's dmamaps and shitz */ 286 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 287 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 288 return -1; 289 } 290 } 291 292 if ((error = bus_dmamem_alloc(sc->dmat, PAGE_SIZE, PAGE_SIZE, 0, 293 seg, 1, &rseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO))) { 294 printf(": cannot allocate scratch buffer (%d)\n", error); 295 return -1; 296 } 297 298 if ((error = bus_dmamem_map(sc->dmat, seg, rseg, PAGE_SIZE, 299 (caddr_t *)&sc->scratch, BUS_DMA_NOWAIT))) { 300 printf(": cannot map scratch buffer (%d)\n", error); 301 return -1; 302 } 303 304 lock = CISS_LOCK_SCRATCH(sc); 305 inq = sc->scratch; 306 if (ciss_inq(sc, inq)) { 307 printf(": adapter inquiry failed\n"); 308 CISS_UNLOCK_SCRATCH(sc, lock); 309 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 310 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 311 return -1; 312 } 313 314 if (!(inq->flags & CISS_INQ_BIGMAP)) { 315 printf(": big map is not supported, flags=%b\n", 316 inq->flags, CISS_INQ_BITS); 317 CISS_UNLOCK_SCRATCH(sc, lock); 318 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 319 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 320 return -1; 321 } 322 323 sc->maxunits = inq->numld; 324 sc->nbus = inq->nscsi_bus; 325 sc->ndrives = inq->buswidth? inq->buswidth : 256; 326 printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s", 327 inq->numld, inq->numld == 1? "" : "s", 328 inq->hw_rev, inq->fw_running, inq->fw_stored); 329 if (sc->cfg.methods & CISS_METH_FIFO64) 330 printf(", 64bit fifo"); 331 else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) 332 printf(", 64bit fifo rro"); 333 printf("\n"); 334 335 CISS_UNLOCK_SCRATCH(sc, lock); 336 337 timeout_set(&sc->sc_hb, ciss_heartbeat, sc); 338 timeout_add_sec(&sc->sc_hb, 3); 339 340 /* map LDs */ 341 if (ciss_ldmap(sc)) { 342 printf("%s: adapter LD map failed\n", sc->sc_dev.dv_xname); 343 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 344 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 345 return -1; 346 } 347 348 if (!(sc->sc_lds = mallocarray(sc->maxunits, sizeof(*sc->sc_lds), 349 M_DEVBUF, M_NOWAIT | M_ZERO))) { 350 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 351 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 352 return -1; 353 } 354 355 sc->sc_flush = CISS_FLUSH_ENABLE; 356 357 saa.saa_adapter_softc = sc; 358 saa.saa_adapter = &ciss_switch; 359 saa.saa_luns = 1; 360 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 361 saa.saa_adapter_buswidth = sc->maxunits; 362 saa.saa_openings = sc->maxcmd; 363 saa.saa_pool = &sc->sc_iopool; 364 saa.saa_quirks = saa.saa_flags = 0; 365 saa.saa_wwpn = saa.saa_wwnn = 0; 366 367 scsibus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev, 368 &saa, scsiprint, NULL); 369 370 #if NBIO > 0 371 /* XXX for now we can only deal w/ one volume. */ 372 if (!scsibus || sc->maxunits > 1) 373 return 0; 374 375 /* now map all the physdevs into their lds */ 376 /* XXX currently we assign all pf 'em into ld#0 */ 377 for (i = 0; i < sc->maxunits; i++) 378 if (!(sc->sc_lds[i] = ciss_pdscan(sc, i))) 379 return 0; 380 381 if (bio_register(&sc->sc_dev, ciss_ioctl) != 0) 382 printf("%s: controller registration failed", 383 sc->sc_dev.dv_xname); 384 385 sc->sc_flags |= CISS_BIO; 386 #ifndef SMALL_KERNEL 387 sc->sensors = mallocarray(sc->maxunits, sizeof(struct ksensor), 388 M_DEVBUF, M_NOWAIT | M_ZERO); 389 if (sc->sensors) { 390 struct device *dev; 391 392 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 393 sizeof(sc->sensordev.xname)); 394 for (i = 0; i < sc->maxunits; i++) { 395 sc->sensors[i].type = SENSOR_DRIVE; 396 sc->sensors[i].status = SENSOR_S_UNKNOWN; 397 dev = scsi_get_link(scsibus, i, 0)->device_softc; 398 strlcpy(sc->sensors[i].desc, dev->dv_xname, 399 sizeof(sc->sensors[i].desc)); 400 strlcpy(sc->sc_lds[i]->xname, dev->dv_xname, 401 sizeof(sc->sc_lds[i]->xname)); 402 sensor_attach(&sc->sensordev, &sc->sensors[i]); 403 } 404 if (sensor_task_register(sc, ciss_sensors, 10) == NULL) 405 free(sc->sensors, M_DEVBUF, 406 sc->maxunits * sizeof(struct ksensor)); 407 else 408 sensordev_install(&sc->sensordev); 409 } 410 #endif /* SMALL_KERNEL */ 411 #endif /* BIO > 0 */ 412 413 return 0; 414 } 415 416 void 417 ciss_shutdown(void *v) 418 { 419 struct ciss_softc *sc = v; 420 421 sc->sc_flush = CISS_FLUSH_DISABLE; 422 timeout_del(&sc->sc_hb); 423 ciss_sync(sc); 424 } 425 426 /* 427 * submit a command and optionally wait for completion. 428 * wait arg abuses SCSI_POLL|SCSI_NOSLEEP flags to request 429 * to wait (SCSI_POLL) and to allow tsleep() (!SCSI_NOSLEEP) 430 * instead of busy loop waiting 431 */ 432 int 433 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) 434 { 435 struct timespec end, now, ts; 436 struct ciss_softc *sc = ccb->ccb_sc; 437 struct ciss_cmd *cmd = &ccb->ccb_cmd; 438 struct ciss_ccb *ccb1; 439 bus_dmamap_t dmap = ccb->ccb_dmamap; 440 u_int64_t addr; 441 uint64_t nsecs; 442 u_int32_t id; 443 int i, error = 0, ret; 444 445 splassert(IPL_BIO); 446 447 if (ccb->ccb_state != CISS_CCB_READY) { 448 printf("%s: ccb %d not ready state=%b\n", sc->sc_dev.dv_xname, 449 cmd->id, ccb->ccb_state, CISS_CCB_BITS); 450 return (EINVAL); 451 } 452 453 if (ccb->ccb_data) { 454 bus_dma_segment_t *sgd; 455 456 if ((error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data, 457 ccb->ccb_len, NULL, flags))) { 458 if (error == EFBIG) 459 printf("more than %d dma segs\n", sc->maxsg); 460 else 461 printf("error %d loading dma map\n", error); 462 if (ccb->ccb_xs) { 463 ccb->ccb_xs->error = XS_DRIVER_STUFFUP; 464 scsi_done(ccb->ccb_xs); 465 ccb->ccb_xs = NULL; 466 } 467 return (error); 468 } 469 cmd->sgin = dmap->dm_nsegs; 470 471 sgd = dmap->dm_segs; 472 CISS_DPRINTF(CISS_D_DMA, ("data=%p/%zu<0x%lx/%lu", 473 ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len)); 474 475 for (i = 0; i < dmap->dm_nsegs; sgd++, i++) { 476 cmd->sgl[i].addr_lo = htole32(sgd->ds_addr); 477 cmd->sgl[i].addr_hi = 478 htole32((u_int64_t)sgd->ds_addr >> 32); 479 cmd->sgl[i].len = htole32(sgd->ds_len); 480 cmd->sgl[i].flags = htole32(0); 481 if (i) 482 CISS_DPRINTF(CISS_D_DMA, 483 (",0x%lx/%lu", sgd->ds_addr, sgd->ds_len)); 484 } 485 486 CISS_DPRINTF(CISS_D_DMA, ("> ")); 487 488 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize, 489 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 490 } else 491 cmd->sgin = 0; 492 cmd->sglen = htole16((u_int16_t)cmd->sgin); 493 bzero(&ccb->ccb_err, sizeof(ccb->ccb_err)); 494 495 bus_dmamap_sync(sc->dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize, 496 BUS_DMASYNC_PREWRITE); 497 498 ccb->ccb_state = CISS_CCB_ONQ; 499 CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); 500 if (sc->cfg.methods & (CISS_METH_FIFO64|CISS_METH_FIFO64_RRO)) { 501 /* 502 * Write the upper 32bits immediately before the lower 503 * 32bits and set bit 63 to indicate 64bit FIFO mode. 504 */ 505 addr = (u_int64_t)ccb->ccb_cmdpa; 506 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_HI, 507 (addr >> 32) | 0x80000000); 508 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_LO, 509 addr & 0x00000000ffffffffULL); 510 } else 511 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ, ccb->ccb_cmdpa); 512 513 /* If we're not waiting for completion we're done. */ 514 if (!(wait & SCSI_POLL)) 515 return (error); 516 517 CISS_DPRINTF(CISS_D_CMD, ("waiting ")); 518 519 i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000; 520 521 if (!(wait & SCSI_NOSLEEP)) { 522 NSEC_TO_TIMESPEC(MSEC_TO_NSEC(i), &ts); 523 nanouptime(&now); 524 timespecadd(&now, &ts, &end); 525 526 for (;;) { 527 ccb->ccb_state = CISS_CCB_POLL; 528 nsecs = TIMESPEC_TO_NSEC(&ts); 529 CISS_DPRINTF(CISS_D_CMD, ("tsleep_nsec(%llu) ", nsecs)); 530 ret = tsleep_nsec(ccb, PRIBIO + 1, "ciss_cmd", nsecs); 531 if (ret == EWOULDBLOCK) 532 break; 533 if (ccb->ccb_state != CISS_CCB_ONQ) { 534 nanouptime(&now); 535 if (timespeccmp(&end, &now, <=)) 536 break; 537 timespecsub(&end, &now, &ts); 538 CISS_DPRINTF(CISS_D_CMD, ("T")); 539 continue; 540 } 541 ccb1 = ccb; 542 543 error = ciss_done(ccb1); 544 if (ccb1 == ccb) 545 return (error); 546 } 547 } else { 548 for (i *= 100; i--;) { 549 DELAY(10); 550 551 if (!(bus_space_read_4(sc->iot, sc->ioh, 552 CISS_ISR) & sc->iem)) { 553 CISS_DPRINTF(CISS_D_CMD, ("N")); 554 continue; 555 } 556 557 if (sc->cfg.methods & CISS_METH_FIFO64) { 558 if (bus_space_read_4(sc->iot, sc->ioh, 559 CISS_OUTQ64_HI) == 0xffffffff) { 560 CISS_DPRINTF(CISS_D_CMD, ("Q")); 561 continue; 562 } 563 id = bus_space_read_4(sc->iot, sc->ioh, 564 CISS_OUTQ64_LO); 565 } else if (sc->cfg.methods & 566 CISS_METH_FIFO64_RRO) { 567 id = bus_space_read_4(sc->iot, sc->ioh, 568 CISS_OUTQ64_LO); 569 if (id == 0xffffffff) { 570 CISS_DPRINTF(CISS_D_CMD, ("Q")); 571 continue; 572 } 573 (void)bus_space_read_4(sc->iot, 574 sc->ioh, CISS_OUTQ64_HI); 575 } else { 576 id = bus_space_read_4(sc->iot, sc->ioh, 577 CISS_OUTQ); 578 if (id == 0xffffffff) { 579 CISS_DPRINTF(CISS_D_CMD, ("Q")); 580 continue; 581 } 582 } 583 584 CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); 585 ccb1 = sc->ccbs + (id >> 2) * sc->ccblen; 586 ccb1->ccb_cmd.id = htole32(id); 587 ccb1->ccb_cmd.id_hi = htole32(0); 588 589 error = ciss_done(ccb1); 590 if (ccb1 == ccb) 591 return (error); 592 } 593 } 594 595 /* if never got a chance to be done above... */ 596 ccb->ccb_err.cmd_stat = CISS_ERR_TMO; 597 error = ciss_done(ccb); 598 599 CISS_DPRINTF(CISS_D_CMD, ("done %d:%d", 600 ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat)); 601 602 return (error); 603 } 604 605 int 606 ciss_done(struct ciss_ccb *ccb) 607 { 608 struct ciss_softc *sc = ccb->ccb_sc; 609 struct scsi_xfer *xs = ccb->ccb_xs; 610 struct ciss_cmd *cmd = &ccb->ccb_cmd; 611 ciss_lock_t lock; 612 int error = 0; 613 614 CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb)); 615 616 if (ccb->ccb_state != CISS_CCB_ONQ) { 617 printf("%s: unqueued ccb %p ready, state=%b\n", 618 sc->sc_dev.dv_xname, ccb, ccb->ccb_state, CISS_CCB_BITS); 619 return 1; 620 } 621 lock = CISS_LOCK(sc); 622 ccb->ccb_state = CISS_CCB_READY; 623 624 if (ccb->ccb_cmd.id & CISS_CMD_ERR) 625 error = ciss_error(ccb); 626 627 if (ccb->ccb_data) { 628 bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0, 629 ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ? 630 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 631 bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); 632 } 633 634 if (xs) { 635 xs->resid = 0; 636 scsi_done(xs); 637 } 638 639 CISS_UNLOCK(sc, lock); 640 641 return error; 642 } 643 644 int 645 ciss_error(struct ciss_ccb *ccb) 646 { 647 struct ciss_softc *sc = ccb->ccb_sc; 648 struct ciss_error *err = &ccb->ccb_err; 649 struct scsi_xfer *xs = ccb->ccb_xs; 650 int rv; 651 652 switch ((rv = letoh16(err->cmd_stat))) { 653 case CISS_ERR_OK: 654 rv = 0; 655 break; 656 657 case CISS_ERR_INVCMD: 658 printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n", 659 sc->sc_dev.dv_xname, ccb->ccb_cmd.id, 660 err->err_info, err->err_type[3], err->err_type[2]); 661 if (xs) { 662 bzero(&xs->sense, sizeof(xs->sense)); 663 xs->sense.error_code = SSD_ERRCODE_VALID | 664 SSD_ERRCODE_CURRENT; 665 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 666 xs->sense.add_sense_code = 0x24; /* ill field */ 667 xs->error = XS_SENSE; 668 } 669 rv = EIO; 670 break; 671 672 case CISS_ERR_TMO: 673 xs->error = XS_TIMEOUT; 674 rv = ETIMEDOUT; 675 break; 676 677 default: 678 if (xs) { 679 switch (err->scsi_stat) { 680 case SCSI_CHECK: 681 xs->error = XS_SENSE; 682 bcopy(&err->sense[0], &xs->sense, 683 sizeof(xs->sense)); 684 rv = EIO; 685 break; 686 687 case SCSI_BUSY: 688 xs->error = XS_BUSY; 689 rv = EBUSY; 690 break; 691 692 default: 693 CISS_DPRINTF(CISS_D_ERR, ("%s: " 694 "cmd_stat %x scsi_stat 0x%x\n", 695 sc->sc_dev.dv_xname, rv, err->scsi_stat)); 696 xs->error = XS_DRIVER_STUFFUP; 697 rv = EIO; 698 break; 699 } 700 xs->resid = letoh32(err->resid); 701 } else 702 rv = EIO; 703 } 704 ccb->ccb_cmd.id &= htole32(~3); 705 706 return rv; 707 } 708 709 int 710 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq) 711 { 712 struct ciss_ccb *ccb; 713 struct ciss_cmd *cmd; 714 int rv; 715 int s; 716 717 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL|SCSI_NOSLEEP); 718 if (ccb == NULL) 719 return ENOMEM; 720 721 ccb->ccb_len = sizeof(*inq); 722 ccb->ccb_data = inq; 723 cmd = &ccb->ccb_cmd; 724 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 725 cmd->tgt2 = 0; 726 cmd->cdblen = 10; 727 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 728 cmd->tmo = htole16(0); 729 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 730 cmd->cdb[0] = CISS_CMD_CTRL_GET; 731 cmd->cdb[6] = CISS_CMS_CTRL_CTRL; 732 cmd->cdb[7] = sizeof(*inq) >> 8; /* biiiig endian */ 733 cmd->cdb[8] = sizeof(*inq) & 0xff; 734 735 s = splbio(); 736 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 737 splx(s); 738 739 scsi_io_put(&sc->sc_iopool, ccb); 740 741 return (rv); 742 } 743 744 int 745 ciss_ldmap(struct ciss_softc *sc) 746 { 747 struct ciss_ccb *ccb; 748 struct ciss_cmd *cmd; 749 struct ciss_ldmap *lmap; 750 ciss_lock_t lock; 751 int total, rv; 752 753 lock = CISS_LOCK_SCRATCH(sc); 754 lmap = sc->scratch; 755 lmap->size = htobe32(sc->maxunits * sizeof(lmap->map)); 756 total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map); 757 758 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL|SCSI_NOSLEEP); 759 if (ccb == NULL) { 760 CISS_UNLOCK_SCRATCH(sc, lock); 761 return ENOMEM; 762 } 763 764 ccb->ccb_len = total; 765 ccb->ccb_data = lmap; 766 cmd = &ccb->ccb_cmd; 767 cmd->tgt = CISS_CMD_MODE_PERIPH; 768 cmd->tgt2 = 0; 769 cmd->cdblen = 12; 770 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 771 cmd->tmo = htole16(30); 772 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 773 cmd->cdb[0] = CISS_CMD_LDMAP; 774 cmd->cdb[8] = total >> 8; /* biiiig endian */ 775 cmd->cdb[9] = total & 0xff; 776 777 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 778 scsi_io_put(&sc->sc_iopool, ccb); 779 CISS_UNLOCK_SCRATCH(sc, lock); 780 781 if (rv) 782 return rv; 783 784 CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n", 785 lmap->map[0].tgt, lmap->map[0].tgt2)); 786 787 return 0; 788 } 789 790 int 791 ciss_sync(struct ciss_softc *sc) 792 { 793 struct ciss_ccb *ccb; 794 struct ciss_cmd *cmd; 795 struct ciss_flush *flush; 796 ciss_lock_t lock; 797 int rv; 798 799 lock = CISS_LOCK_SCRATCH(sc); 800 flush = sc->scratch; 801 bzero(flush, sizeof(*flush)); 802 flush->flush = sc->sc_flush; 803 804 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL|SCSI_NOSLEEP); 805 if (ccb == NULL) { 806 CISS_UNLOCK_SCRATCH(sc, lock); 807 return ENOMEM; 808 } 809 810 ccb->ccb_len = sizeof(*flush); 811 ccb->ccb_data = flush; 812 cmd = &ccb->ccb_cmd; 813 cmd->tgt = CISS_CMD_MODE_PERIPH; 814 cmd->tgt2 = 0; 815 cmd->cdblen = 10; 816 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 817 cmd->tmo = htole16(0); 818 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 819 cmd->cdb[0] = CISS_CMD_CTRL_SET; 820 cmd->cdb[6] = CISS_CMS_CTRL_FLUSH; 821 cmd->cdb[7] = sizeof(*flush) >> 8; /* biiiig endian */ 822 cmd->cdb[8] = sizeof(*flush) & 0xff; 823 824 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 825 scsi_io_put(&sc->sc_iopool, ccb); 826 CISS_UNLOCK_SCRATCH(sc, lock); 827 828 return rv; 829 } 830 831 void 832 ciss_scsi_cmd(struct scsi_xfer *xs) 833 { 834 struct scsi_link *link = xs->sc_link; 835 u_int8_t target = link->target; 836 struct ciss_ccb *ccb; 837 struct ciss_cmd *cmd; 838 ciss_lock_t lock; 839 840 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd ")); 841 842 if (xs->cmdlen > CISS_MAX_CDB) { 843 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 844 bzero(&xs->sense, sizeof(xs->sense)); 845 xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT; 846 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 847 xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */ 848 xs->error = XS_SENSE; 849 scsi_done(xs); 850 return; 851 } 852 853 xs->error = XS_NOERROR; 854 855 /* XXX emulate SYNCHRONIZE_CACHE ??? */ 856 857 ccb = xs->io; 858 859 cmd = &ccb->ccb_cmd; 860 ccb->ccb_len = xs->datalen; 861 ccb->ccb_data = xs->data; 862 ccb->ccb_xs = xs; 863 cmd->tgt = CISS_CMD_MODE_LD | target; 864 cmd->tgt2 = 0; 865 cmd->cdblen = xs->cmdlen; 866 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 867 if (xs->flags & SCSI_DATA_IN) 868 cmd->flags |= CISS_CDB_IN; 869 else if (xs->flags & SCSI_DATA_OUT) 870 cmd->flags |= CISS_CDB_OUT; 871 cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000); 872 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 873 bcopy(&xs->cmd, &cmd->cdb[0], CISS_MAX_CDB); 874 875 lock = CISS_LOCK(sc); 876 ciss_cmd(ccb, BUS_DMA_WAITOK, xs->flags & (SCSI_POLL|SCSI_NOSLEEP)); 877 CISS_UNLOCK(sc, lock); 878 } 879 880 int 881 ciss_intr(void *v) 882 { 883 struct ciss_softc *sc = v; 884 struct ciss_ccb *ccb; 885 bus_size_t reg; 886 u_int32_t id; 887 int hit = 0; 888 889 CISS_DPRINTF(CISS_D_INTR, ("intr ")); 890 891 if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_ISR) & sc->iem)) 892 return 0; 893 894 if (sc->cfg.methods & CISS_METH_FIFO64) 895 reg = CISS_OUTQ64_HI; 896 else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) 897 reg = CISS_OUTQ64_LO; 898 else 899 reg = CISS_OUTQ; 900 while ((id = bus_space_read_4(sc->iot, sc->ioh, reg)) != 0xffffffff) { 901 if (reg == CISS_OUTQ64_HI) 902 id = bus_space_read_4(sc->iot, sc->ioh, 903 CISS_OUTQ64_LO); 904 else if (reg == CISS_OUTQ64_LO) 905 (void)bus_space_read_4(sc->iot, sc->ioh, 906 CISS_OUTQ64_HI); 907 ccb = sc->ccbs + (id >> 2) * sc->ccblen; 908 ccb->ccb_cmd.id = htole32(id); 909 ccb->ccb_cmd.id_hi = htole32(0); /* ignore the upper 32bits */ 910 if (ccb->ccb_state == CISS_CCB_POLL) { 911 ccb->ccb_state = CISS_CCB_ONQ; 912 wakeup(ccb); 913 } else 914 ciss_done(ccb); 915 916 hit = 1; 917 } 918 CISS_DPRINTF(CISS_D_INTR, ("exit ")); 919 return hit; 920 } 921 922 void 923 ciss_heartbeat(void *v) 924 { 925 struct ciss_softc *sc = v; 926 u_int32_t hb; 927 928 hb = bus_space_read_4(sc->iot, sc->cfg_ioh, 929 sc->cfgoff + offsetof(struct ciss_config, heartbeat)); 930 if (hb == sc->heartbeat) { 931 sc->fibrillation++; 932 CISS_DPRINTF(CISS_D_ERR, ("%s: fibrillation #%d (value=%d)\n", 933 sc->sc_dev.dv_xname, sc->fibrillation, hb)); 934 if (sc->fibrillation >= 11) { 935 /* No heartbeat for 33 seconds */ 936 panic("%s: dead", sc->sc_dev.dv_xname); /* XXX reset! */ 937 } 938 } else { 939 sc->heartbeat = hb; 940 if (sc->fibrillation) { 941 CISS_DPRINTF(CISS_D_ERR, ("%s: " 942 "fibrillation ended (value=%d)\n", 943 sc->sc_dev.dv_xname, hb)); 944 } 945 sc->fibrillation = 0; 946 } 947 948 timeout_add_sec(&sc->sc_hb, 3); 949 } 950 951 int 952 ciss_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) 953 { 954 #if NBIO > 0 955 return ciss_ioctl(link->bus->sb_adapter_softc, cmd, addr); 956 #else 957 return ENOTTY; 958 #endif 959 } 960 961 #if NBIO > 0 962 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 }; 963 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 964 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 965 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 966 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 967 968 int 969 ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr) 970 { 971 struct ciss_softc *sc = (struct ciss_softc *)dev; 972 struct bioc_inq *bi; 973 struct bioc_vol *bv; 974 struct bioc_disk *bd; 975 struct bioc_blink *bb; 976 /* struct bioc_alarm *ba; */ 977 /* struct bioc_setstate *bss; */ 978 struct ciss_ldid *ldid; 979 struct ciss_ldstat *ldstat; 980 struct ciss_pdid *pdid; 981 struct ciss_blink *blink; 982 struct ciss_ld *ldp; 983 ciss_lock_t lock; 984 u_int8_t drv; 985 int ld, pd, error = 0; 986 u_int blks; 987 988 if (!(sc->sc_flags & CISS_BIO)) 989 return ENOTTY; 990 991 lock = CISS_LOCK(sc); 992 switch (cmd) { 993 case BIOCINQ: 994 bi = (struct bioc_inq *)addr; 995 strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev)); 996 bi->bi_novol = sc->maxunits; 997 bi->bi_nodisk = sc->ndrives; 998 break; 999 1000 case BIOCVOL: 1001 bv = (struct bioc_vol *)addr; 1002 if (bv->bv_volid > sc->maxunits) { 1003 error = EINVAL; 1004 break; 1005 } 1006 ldp = sc->sc_lds[bv->bv_volid]; 1007 if (!ldp) { 1008 error = EINVAL; 1009 break; 1010 } 1011 ldid = sc->scratch; 1012 if ((error = ciss_ldid(sc, bv->bv_volid, ldid))) 1013 break; 1014 /* params 30:88:ff:00:00:00:00:00:00:00:00:00:00:00:20:00 */ 1015 bv->bv_status = BIOC_SVINVALID; 1016 blks = (u_int)letoh16(ldid->nblocks[1]) << 16 | 1017 letoh16(ldid->nblocks[0]); 1018 bv->bv_size = blks * (uint64_t)letoh16(ldid->blksize); 1019 bv->bv_level = ciss_level[ldid->type]; 1020 bv->bv_nodisk = ldp->ndrives; 1021 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1022 strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor)); 1023 ldstat = sc->scratch; 1024 bzero(ldstat, sizeof(*ldstat)); 1025 if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat))) 1026 break; 1027 bv->bv_percent = -1; 1028 bv->bv_seconds = 0; 1029 if (ldstat->stat < nitems(ciss_stat)) 1030 bv->bv_status = ciss_stat[ldstat->stat]; 1031 if (bv->bv_status == BIOC_SVREBUILD || 1032 bv->bv_status == BIOC_SVBUILDING) 1033 bv->bv_percent = (blks - 1034 (((u_int)ldstat->prog[3] << 24) | 1035 ((u_int)ldstat->prog[2] << 16) | 1036 ((u_int)ldstat->prog[1] << 8) | 1037 (u_int)ldstat->prog[0])) * 100ULL / blks; 1038 break; 1039 1040 case BIOCDISK: 1041 bd = (struct bioc_disk *)addr; 1042 if (bd->bd_volid > sc->maxunits) { 1043 error = EINVAL; 1044 break; 1045 } 1046 ldp = sc->sc_lds[bd->bd_volid]; 1047 if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) { 1048 error = EINVAL; 1049 break; 1050 } 1051 ldstat = sc->scratch; 1052 if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) 1053 break; 1054 bd->bd_status = -1; 1055 if (ldstat->stat == CISS_LD_REBLD && 1056 ldstat->bigrebuild == ldp->tgts[pd]) 1057 bd->bd_status = BIOC_SDREBUILD; 1058 if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT), 1059 ldstat->bigfailed)) { 1060 bd->bd_status = BIOC_SDFAILED; 1061 bd->bd_size = 0; 1062 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1063 sc->ndrives; 1064 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1065 bd->bd_lun = 0; 1066 bd->bd_vendor[0] = '\0'; 1067 bd->bd_serial[0] = '\0'; 1068 bd->bd_procdev[0] = '\0'; 1069 } else { 1070 pdid = sc->scratch; 1071 if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, 1072 SCSI_POLL))) 1073 break; 1074 if (bd->bd_status < 0) { 1075 if (pdid->config & CISS_PD_SPARE) 1076 bd->bd_status = BIOC_SDHOTSPARE; 1077 else if (pdid->present & CISS_PD_PRESENT) 1078 bd->bd_status = BIOC_SDONLINE; 1079 else 1080 bd->bd_status = BIOC_SDINVALID; 1081 } 1082 bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) * 1083 letoh16(pdid->blksz); 1084 bd->bd_channel = pdid->bus; 1085 bd->bd_target = pdid->target; 1086 bd->bd_lun = 0; 1087 strlcpy(bd->bd_vendor, pdid->model, 1088 sizeof(bd->bd_vendor)); 1089 strlcpy(bd->bd_serial, pdid->serial, 1090 sizeof(bd->bd_serial)); 1091 bd->bd_procdev[0] = '\0'; 1092 } 1093 break; 1094 1095 case BIOCBLINK: 1096 bb = (struct bioc_blink *)addr; 1097 blink = sc->scratch; 1098 error = EINVAL; 1099 /* XXX workaround completely dumb scsi addressing */ 1100 for (ld = 0; ld < sc->maxunits; ld++) { 1101 ldp = sc->sc_lds[ld]; 1102 if (!ldp) 1103 continue; 1104 if (sc->ndrives == 256) 1105 drv = bb->bb_target; 1106 else 1107 drv = CISS_BIGBIT + 1108 bb->bb_channel * sc->ndrives + 1109 bb->bb_target; 1110 for (pd = 0; pd < ldp->ndrives; pd++) 1111 if (ldp->tgts[pd] == drv) 1112 error = ciss_blink(sc, ld, pd, 1113 bb->bb_status, blink); 1114 } 1115 break; 1116 1117 case BIOCALARM: 1118 case BIOCSETSTATE: 1119 default: 1120 CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n", 1121 sc->sc_dev.dv_xname)); 1122 error = ENOTTY; 1123 } 1124 CISS_UNLOCK(sc, lock); 1125 1126 return error; 1127 } 1128 1129 #ifndef SMALL_KERNEL 1130 void 1131 ciss_sensors(void *v) 1132 { 1133 struct ciss_softc *sc = v; 1134 struct ciss_ldstat *ldstat; 1135 int i, error; 1136 1137 for (i = 0; i < sc->maxunits; i++) { 1138 ldstat = sc->scratch; 1139 if ((error = ciss_ldstat(sc, i, ldstat))) { 1140 sc->sensors[i].value = 0; 1141 sc->sensors[i].status = SENSOR_S_UNKNOWN; 1142 continue; 1143 } 1144 1145 switch (ldstat->stat) { 1146 case CISS_LD_OK: 1147 sc->sensors[i].value = SENSOR_DRIVE_ONLINE; 1148 sc->sensors[i].status = SENSOR_S_OK; 1149 break; 1150 1151 case CISS_LD_DEGRAD: 1152 sc->sensors[i].value = SENSOR_DRIVE_PFAIL; 1153 sc->sensors[i].status = SENSOR_S_WARN; 1154 break; 1155 1156 case CISS_LD_EXPND: 1157 case CISS_LD_QEXPND: 1158 case CISS_LD_RBLDRD: 1159 case CISS_LD_REBLD: 1160 sc->sensors[i].value = SENSOR_DRIVE_REBUILD; 1161 sc->sensors[i].status = SENSOR_S_WARN; 1162 break; 1163 1164 case CISS_LD_NORDY: 1165 case CISS_LD_PDINV: 1166 case CISS_LD_PDUNC: 1167 case CISS_LD_FAILED: 1168 case CISS_LD_UNCONF: 1169 sc->sensors[i].value = SENSOR_DRIVE_FAIL; 1170 sc->sensors[i].status = SENSOR_S_CRIT; 1171 break; 1172 1173 default: 1174 sc->sensors[i].value = 0; 1175 sc->sensors[i].status = SENSOR_S_UNKNOWN; 1176 } 1177 } 1178 } 1179 #endif /* SMALL_KERNEL */ 1180 1181 int 1182 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id) 1183 { 1184 struct ciss_ccb *ccb; 1185 struct ciss_cmd *cmd; 1186 int rv; 1187 int s; 1188 1189 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 1190 if (ccb == NULL) 1191 return ENOMEM; 1192 1193 ccb->ccb_len = sizeof(*id); 1194 ccb->ccb_data = id; 1195 cmd = &ccb->ccb_cmd; 1196 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1197 cmd->tgt2 = 0; 1198 cmd->cdblen = 10; 1199 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 1200 cmd->tmo = htole16(0); 1201 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1202 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1203 cmd->cdb[5] = target; 1204 cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT; 1205 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 1206 cmd->cdb[8] = sizeof(*id) & 0xff; 1207 1208 s = splbio(); 1209 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1210 splx(s); 1211 1212 scsi_io_put(&sc->sc_iopool, ccb); 1213 1214 return (rv); 1215 } 1216 1217 int 1218 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat) 1219 { 1220 struct ciss_ccb *ccb; 1221 struct ciss_cmd *cmd; 1222 int rv; 1223 int s; 1224 1225 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 1226 if (ccb == NULL) 1227 return ENOMEM; 1228 1229 ccb->ccb_len = sizeof(*stat); 1230 ccb->ccb_data = stat; 1231 cmd = &ccb->ccb_cmd; 1232 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1233 cmd->tgt2 = 0; 1234 cmd->cdblen = 10; 1235 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 1236 cmd->tmo = htole16(0); 1237 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1238 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1239 cmd->cdb[5] = target; 1240 cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT; 1241 cmd->cdb[7] = sizeof(*stat) >> 8; /* biiiig endian */ 1242 cmd->cdb[8] = sizeof(*stat) & 0xff; 1243 1244 s = splbio(); 1245 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1246 splx(s); 1247 1248 scsi_io_put(&sc->sc_iopool, ccb); 1249 1250 return (rv); 1251 } 1252 1253 int 1254 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait) 1255 { 1256 struct ciss_ccb *ccb; 1257 struct ciss_cmd *cmd; 1258 int rv; 1259 int s; 1260 1261 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 1262 if (ccb == NULL) 1263 return ENOMEM; 1264 1265 ccb->ccb_len = sizeof(*id); 1266 ccb->ccb_data = id; 1267 cmd = &ccb->ccb_cmd; 1268 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1269 cmd->tgt2 = 0; 1270 cmd->cdblen = 10; 1271 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 1272 cmd->tmo = htole16(0); 1273 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1274 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1275 cmd->cdb[2] = drv; 1276 cmd->cdb[6] = CISS_CMS_CTRL_PDID; 1277 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 1278 cmd->cdb[8] = sizeof(*id) & 0xff; 1279 1280 s = splbio(); 1281 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, wait); 1282 splx(s); 1283 1284 scsi_io_put(&sc->sc_iopool, ccb); 1285 1286 return (rv); 1287 } 1288 1289 1290 struct ciss_ld * 1291 ciss_pdscan(struct ciss_softc *sc, int ld) 1292 { 1293 struct ciss_pdid *pdid; 1294 struct ciss_ld *ldp; 1295 u_int8_t drv, buf[128]; 1296 int i, j, k = 0; 1297 1298 pdid = sc->scratch; 1299 if (sc->ndrives == 256) { 1300 for (i = 0; i < CISS_BIGBIT; i++) 1301 if (!ciss_pdid(sc, i, pdid, SCSI_NOSLEEP|SCSI_POLL) && 1302 (pdid->present & CISS_PD_PRESENT)) 1303 buf[k++] = i; 1304 } else 1305 for (i = 0; i < sc->nbus; i++) 1306 for (j = 0; j < sc->ndrives; j++) { 1307 drv = CISS_BIGBIT + i * sc->ndrives + j; 1308 if (!ciss_pdid(sc, drv, pdid, 1309 SCSI_NOSLEEP|SCSI_POLL)) 1310 buf[k++] = drv; 1311 } 1312 1313 if (!k) 1314 return NULL; 1315 1316 ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT); 1317 if (!ldp) 1318 return NULL; 1319 1320 bzero(&ldp->bling, sizeof(ldp->bling)); 1321 ldp->ndrives = k; 1322 bcopy(buf, ldp->tgts, k); 1323 return ldp; 1324 } 1325 1326 int 1327 ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat, 1328 struct ciss_blink *blink) 1329 { 1330 struct ciss_ccb *ccb; 1331 struct ciss_cmd *cmd; 1332 struct ciss_ld *ldp; 1333 int rv; 1334 int s; 1335 1336 if (ld > sc->maxunits) 1337 return EINVAL; 1338 1339 ldp = sc->sc_lds[ld]; 1340 if (!ldp || pd > ldp->ndrives) 1341 return EINVAL; 1342 1343 ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 : 1344 CISS_BLINK_ALL; 1345 bcopy(&ldp->bling, blink, sizeof(*blink)); 1346 1347 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 1348 if (ccb == NULL) 1349 return ENOMEM; 1350 1351 ccb->ccb_len = sizeof(*blink); 1352 ccb->ccb_data = blink; 1353 cmd = &ccb->ccb_cmd; 1354 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1355 cmd->tgt2 = 0; 1356 cmd->cdblen = 10; 1357 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 1358 cmd->tmo = htole16(0); 1359 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1360 cmd->cdb[0] = CISS_CMD_CTRL_SET; 1361 cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK; 1362 cmd->cdb[7] = sizeof(*blink) >> 8; /* biiiig endian */ 1363 cmd->cdb[8] = sizeof(*blink) & 0xff; 1364 1365 s = splbio(); 1366 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1367 splx(s); 1368 1369 scsi_io_put(&sc->sc_iopool, ccb); 1370 1371 return (rv); 1372 } 1373 #endif 1374