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