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