1 /* $OpenBSD: ciss.c,v 1.34 2009/04/29 08:24:26 reyk 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", 336 inq->numld, inq->numld == 1? "" : "s", 337 inq->hw_rev, inq->fw_running, inq->fw_stored); 338 if (sc->cfg.methods & CISS_METH_FIFO64) 339 printf(", 64bit fifo"); 340 else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) 341 printf(", 64bit fifo rro"); 342 printf("\n"); 343 344 CISS_UNLOCK_SCRATCH(sc, lock); 345 346 timeout_set(&sc->sc_hb, ciss_heartbeat, sc); 347 timeout_add_sec(&sc->sc_hb, 3); 348 349 /* map LDs */ 350 if (ciss_ldmap(sc)) { 351 printf("%s: adapter LD map failed\n", sc->sc_dev.dv_xname); 352 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 353 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 354 return -1; 355 } 356 357 if (!(sc->sc_lds = malloc(sc->maxunits * sizeof(*sc->sc_lds), 358 M_DEVBUF, M_NOWAIT | M_ZERO))) { 359 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 360 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 361 return -1; 362 } 363 364 sc->sc_flush = CISS_FLUSH_ENABLE; 365 if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) { 366 printf(": unable to establish shutdown hook\n"); 367 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 368 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 369 return -1; 370 } 371 372 #if 0 373 if (kthread_create(ciss_kthread, sc, NULL, "%s", sc->sc_dev.dv_xname)) { 374 printf(": unable to create kernel thread\n"); 375 shutdownhook_disestablish(sc->sc_sh); 376 bus_dmamem_free(sc->dmat, sc->cmdseg, 1); 377 bus_dmamap_destroy(sc->dmat, sc->cmdmap); 378 return -1; 379 } 380 #endif 381 382 sc->sc_link.device = &ciss_dev; 383 sc->sc_link.adapter_softc = sc; 384 sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1); 385 #if NBIO > 0 386 /* XXX Reserve some ccb's for sensor and bioctl. */ 387 if (sc->maxunits < 2 && sc->sc_link.openings > 2) 388 sc->sc_link.openings -= 2; 389 #endif 390 sc->sc_link.adapter = &ciss_switch; 391 sc->sc_link.adapter_target = sc->maxunits; 392 sc->sc_link.adapter_buswidth = sc->maxunits; 393 bzero(&saa, sizeof(saa)); 394 saa.saa_sc_link = &sc->sc_link; 395 scsibus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev, 396 &saa, scsiprint, NULL); 397 398 #if 0 399 sc->sc_link_raw.device = &ciss_raw_dev; 400 sc->sc_link_raw.adapter_softc = sc; 401 sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1); 402 sc->sc_link_raw.adapter = &ciss_raw_switch; 403 sc->sc_link_raw.adapter_target = sc->ndrives; 404 sc->sc_link_raw.adapter_buswidth = sc->ndrives; 405 bzero(&saa, sizeof(saa)); 406 saa.saa_sc_link = &sc->sc_link_raw; 407 rawbus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev, 408 &saa, scsiprint, NULL); 409 #endif 410 411 #if NBIO > 0 412 /* XXX for now we can only deal w/ one volume and need reserved ccbs. */ 413 if (!scsibus || sc->maxunits > 1 || sc->sc_link.openings == sc->maxcmd) 414 return 0; 415 416 /* now map all the physdevs into their lds */ 417 /* XXX currently we assign all pf 'em into ld#0 */ 418 for (i = 0; i < sc->maxunits; i++) 419 if (!(sc->sc_lds[i] = ciss_pdscan(sc, i))) 420 return 0; 421 422 if (bio_register(&sc->sc_dev, ciss_ioctl) != 0) 423 printf("%s: controller registration failed", 424 sc->sc_dev.dv_xname); 425 426 sc->sc_flags |= CISS_BIO; 427 #ifndef SMALL_KERNEL 428 sc->sensors = malloc(sizeof(struct ksensor) * sc->maxunits, 429 M_DEVBUF, M_NOWAIT | M_ZERO); 430 if (sc->sensors) { 431 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 432 sizeof(sc->sensordev.xname)); 433 for (i = 0; i < sc->maxunits; 434 sensor_attach(&sc->sensordev, &sc->sensors[i++])) { 435 sc->sensors[i].type = SENSOR_DRIVE; 436 sc->sensors[i].status = SENSOR_S_UNKNOWN; 437 strlcpy(sc->sensors[i].desc, ((struct device *) 438 scsibus->sc_link[i][0]->device_softc)->dv_xname, 439 sizeof(sc->sensors[i].desc)); 440 strlcpy(sc->sc_lds[i]->xname, ((struct device *) 441 scsibus->sc_link[i][0]->device_softc)->dv_xname, 442 sizeof(sc->sc_lds[i]->xname)); 443 } 444 if (sensor_task_register(sc, ciss_sensors, 10) == NULL) 445 free(sc->sensors, M_DEVBUF); 446 else 447 sensordev_install(&sc->sensordev); 448 } 449 #endif /* SMALL_KERNEL */ 450 #endif /* BIO > 0 */ 451 452 return 0; 453 } 454 455 void 456 ciss_shutdown(void *v) 457 { 458 struct ciss_softc *sc = v; 459 460 sc->sc_flush = CISS_FLUSH_DISABLE; 461 timeout_del(&sc->sc_hb); 462 ciss_sync(sc); 463 } 464 465 void 466 cissminphys(struct buf *bp, struct scsi_link *sl) 467 { 468 #if 0 /* TODO */ 469 #define CISS_MAXFER (PAGE_SIZE * (sc->maxsg + 1)) 470 if (bp->b_bcount > CISS_MAXFER) 471 bp->b_bcount = CISS_MAXFER; 472 #endif 473 minphys(bp); 474 } 475 476 /* 477 * submit a command and optionally wait for completition. 478 * wait arg abuses SCSI_POLL|SCSI_NOSLEEP flags to request 479 * to wait (SCSI_POLL) and to allow tsleep() (!SCSI_NOSLEEP) 480 * instead of busy loop waiting 481 */ 482 int 483 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) 484 { 485 struct ciss_softc *sc = ccb->ccb_sc; 486 struct ciss_cmd *cmd = &ccb->ccb_cmd; 487 struct ciss_ccb *ccb1; 488 bus_dmamap_t dmap = ccb->ccb_dmamap; 489 u_int64_t addr; 490 u_int32_t id; 491 int i, tohz, error = 0; 492 493 if (ccb->ccb_state != CISS_CCB_READY) { 494 printf("%s: ccb %d not ready state=%b\n", sc->sc_dev.dv_xname, 495 cmd->id, ccb->ccb_state, CISS_CCB_BITS); 496 return (EINVAL); 497 } 498 499 if (ccb->ccb_data) { 500 bus_dma_segment_t *sgd; 501 502 if ((error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data, 503 ccb->ccb_len, NULL, flags))) { 504 if (error == EFBIG) 505 printf("more than %d dma segs\n", sc->maxsg); 506 else 507 printf("error %d loading dma map\n", error); 508 ciss_put_ccb(ccb); 509 return (error); 510 } 511 cmd->sgin = dmap->dm_nsegs; 512 513 sgd = dmap->dm_segs; 514 CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%u", 515 ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len)); 516 517 for (i = 0; i < dmap->dm_nsegs; sgd++, i++) { 518 cmd->sgl[i].addr_lo = htole32(sgd->ds_addr); 519 cmd->sgl[i].addr_hi = 520 htole32((u_int64_t)sgd->ds_addr >> 32); 521 cmd->sgl[i].len = htole32(sgd->ds_len); 522 cmd->sgl[i].flags = htole32(0); 523 if (i) 524 CISS_DPRINTF(CISS_D_DMA, 525 (",0x%lx/%u", sgd->ds_addr, sgd->ds_len)); 526 } 527 528 CISS_DPRINTF(CISS_D_DMA, ("> ")); 529 530 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize, 531 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 532 } else 533 cmd->sgin = 0; 534 cmd->sglen = htole16((u_int16_t)cmd->sgin); 535 bzero(&ccb->ccb_err, sizeof(ccb->ccb_err)); 536 537 bus_dmamap_sync(sc->dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize, 538 BUS_DMASYNC_PREWRITE); 539 540 if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP)) 541 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR, 542 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) | sc->iem); 543 544 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link); 545 ccb->ccb_state = CISS_CCB_ONQ; 546 CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); 547 if (sc->cfg.methods & (CISS_METH_FIFO64|CISS_METH_FIFO64_RRO)) { 548 /* 549 * Write the upper 32bits immediately before the lower 550 * 32bits and set bit 63 to indicate 64bit FIFO mode. 551 */ 552 addr = (u_int64_t)ccb->ccb_cmdpa; 553 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_HI, 554 (addr >> 32) | 0x80000000); 555 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_LO, 556 addr & 0x00000000ffffffffULL); 557 } else 558 bus_space_write_4(sc->iot, sc->ioh, CISS_INQ, ccb->ccb_cmdpa); 559 560 if (wait & SCSI_POLL) { 561 struct timeval tv; 562 int etick; 563 CISS_DPRINTF(CISS_D_CMD, ("waiting ")); 564 565 i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000; 566 tv.tv_sec = i / 1000; 567 tv.tv_usec = (i % 1000) * 1000; 568 tohz = tvtohz(&tv); 569 if (tohz == 0) 570 tohz = 1; 571 for (i *= 100, etick = tick + tohz; i--; ) { 572 if (!(wait & SCSI_NOSLEEP)) { 573 ccb->ccb_state = CISS_CCB_POLL; 574 CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz)); 575 if (tsleep(ccb, PRIBIO + 1, "ciss_cmd", 576 tohz) == EWOULDBLOCK) { 577 break; 578 } 579 if (ccb->ccb_state != CISS_CCB_ONQ) { 580 tohz = etick - tick; 581 if (tohz <= 0) 582 break; 583 CISS_DPRINTF(CISS_D_CMD, ("T")); 584 continue; 585 } 586 ccb1 = ccb; 587 } else { 588 DELAY(10); 589 590 if (!(bus_space_read_4(sc->iot, sc->ioh, 591 CISS_ISR) & sc->iem)) { 592 CISS_DPRINTF(CISS_D_CMD, ("N")); 593 continue; 594 } 595 596 if (sc->cfg.methods & CISS_METH_FIFO64) { 597 if (bus_space_read_4(sc->iot, sc->ioh, 598 CISS_OUTQ64_HI) == 0xffffffff) { 599 CISS_DPRINTF(CISS_D_CMD, ("Q")); 600 continue; 601 } 602 id = bus_space_read_4(sc->iot, sc->ioh, 603 CISS_OUTQ64_LO); 604 } else if (sc->cfg.methods & 605 CISS_METH_FIFO64_RRO) { 606 id = bus_space_read_4(sc->iot, sc->ioh, 607 CISS_OUTQ64_LO); 608 if (id == 0xffffffff) { 609 CISS_DPRINTF(CISS_D_CMD, ("Q")); 610 continue; 611 } 612 (void)bus_space_read_4(sc->iot, 613 sc->ioh, CISS_OUTQ64_HI); 614 } else { 615 id = bus_space_read_4(sc->iot, sc->ioh, 616 CISS_OUTQ); 617 if (id == 0xffffffff) { 618 CISS_DPRINTF(CISS_D_CMD, ("Q")); 619 continue; 620 } 621 } 622 623 CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); 624 ccb1 = sc->ccbs + (id >> 2) * sc->ccblen; 625 ccb1->ccb_cmd.id = htole32(id); 626 ccb1->ccb_cmd.id_hi = htole32(0); 627 } 628 629 error = ciss_done(ccb1); 630 if (ccb1 == ccb) 631 break; 632 } 633 634 /* if never got a chance to be done above... */ 635 if (ccb->ccb_state != CISS_CCB_FREE) { 636 ccb->ccb_err.cmd_stat = CISS_ERR_TMO; 637 error = ciss_done(ccb); 638 } 639 640 CISS_DPRINTF(CISS_D_CMD, ("done %d:%d", 641 ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat)); 642 } 643 644 if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP)) 645 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR, 646 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) & ~sc->iem); 647 648 return (error); 649 } 650 651 int 652 ciss_done(struct ciss_ccb *ccb) 653 { 654 struct ciss_softc *sc = ccb->ccb_sc; 655 struct scsi_xfer *xs = ccb->ccb_xs; 656 ciss_lock_t lock; 657 int error = 0; 658 659 CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb)); 660 661 if (ccb->ccb_state != CISS_CCB_ONQ) { 662 printf("%s: unqueued ccb %p ready, state=%b\n", 663 sc->sc_dev.dv_xname, ccb, ccb->ccb_state, CISS_CCB_BITS); 664 return 1; 665 } 666 667 lock = CISS_LOCK(sc); 668 ccb->ccb_state = CISS_CCB_READY; 669 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link); 670 671 if (ccb->ccb_cmd.id & CISS_CMD_ERR) 672 error = ciss_error(ccb); 673 674 if (ccb->ccb_data) { 675 bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0, 676 ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ? 677 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 678 bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); 679 ccb->ccb_xs = NULL; 680 ccb->ccb_data = NULL; 681 } 682 683 ciss_put_ccb(ccb); 684 685 if (xs) { 686 xs->resid = 0; 687 xs->flags |= ITSDONE; 688 CISS_DPRINTF(CISS_D_CMD, ("scsi_done(%p) ", xs)); 689 scsi_done(xs); 690 } 691 CISS_UNLOCK(sc, lock); 692 693 return error; 694 } 695 696 int 697 ciss_error(struct ciss_ccb *ccb) 698 { 699 struct ciss_softc *sc = ccb->ccb_sc; 700 struct ciss_error *err = &ccb->ccb_err; 701 struct scsi_xfer *xs = ccb->ccb_xs; 702 int rv; 703 704 switch ((rv = letoh16(err->cmd_stat))) { 705 case CISS_ERR_OK: 706 rv = 0; 707 break; 708 709 case CISS_ERR_INVCMD: 710 printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n", 711 sc->sc_dev.dv_xname, ccb->ccb_cmd.id, 712 err->err_info, err->err_type[3], err->err_type[2]); 713 if (xs) { 714 bzero(&xs->sense, sizeof(xs->sense)); 715 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 716 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 717 xs->sense.add_sense_code = 0x24; /* ill field */ 718 xs->error = XS_SENSE; 719 } 720 rv = EIO; 721 break; 722 723 case CISS_ERR_TMO: 724 xs->error = XS_TIMEOUT; 725 rv = ETIMEDOUT; 726 break; 727 728 default: 729 if (xs) { 730 switch (err->scsi_stat) { 731 case SCSI_CHECK: 732 xs->error = XS_SENSE; 733 bcopy(&err->sense[0], &xs->sense, 734 sizeof(xs->sense)); 735 rv = EIO; 736 break; 737 738 case SCSI_BUSY: 739 xs->error = XS_BUSY; 740 rv = EBUSY; 741 break; 742 743 default: 744 CISS_DPRINTF(CISS_D_ERR, ("%s: " 745 "cmd_stat %x scsi_stat 0x%x\n", 746 sc->sc_dev.dv_xname, rv, err->scsi_stat)); 747 xs->error = XS_DRIVER_STUFFUP; 748 rv = EIO; 749 break; 750 } 751 xs->resid = letoh32(err->resid); 752 } else 753 rv = EIO; 754 } 755 ccb->ccb_cmd.id &= htole32(~3); 756 757 return rv; 758 } 759 760 int 761 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq) 762 { 763 struct ciss_ccb *ccb; 764 struct ciss_cmd *cmd; 765 766 ccb = ciss_get_ccb(sc); 767 ccb->ccb_len = sizeof(*inq); 768 ccb->ccb_data = inq; 769 cmd = &ccb->ccb_cmd; 770 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 771 cmd->tgt2 = 0; 772 cmd->cdblen = 10; 773 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 774 cmd->tmo = htole16(0); 775 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 776 cmd->cdb[0] = CISS_CMD_CTRL_GET; 777 cmd->cdb[6] = CISS_CMS_CTRL_CTRL; 778 cmd->cdb[7] = sizeof(*inq) >> 8; /* biiiig endian */ 779 cmd->cdb[8] = sizeof(*inq) & 0xff; 780 781 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 782 } 783 784 int 785 ciss_ldmap(struct ciss_softc *sc) 786 { 787 struct ciss_ccb *ccb; 788 struct ciss_cmd *cmd; 789 struct ciss_ldmap *lmap; 790 ciss_lock_t lock; 791 int total, rv; 792 793 lock = CISS_LOCK_SCRATCH(sc); 794 lmap = sc->scratch; 795 lmap->size = htobe32(sc->maxunits * sizeof(lmap->map)); 796 total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map); 797 798 ccb = ciss_get_ccb(sc); 799 ccb->ccb_len = total; 800 ccb->ccb_data = lmap; 801 cmd = &ccb->ccb_cmd; 802 cmd->tgt = CISS_CMD_MODE_PERIPH; 803 cmd->tgt2 = 0; 804 cmd->cdblen = 12; 805 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 806 cmd->tmo = htole16(30); 807 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 808 cmd->cdb[0] = CISS_CMD_LDMAP; 809 cmd->cdb[8] = total >> 8; /* biiiig endian */ 810 cmd->cdb[9] = total & 0xff; 811 812 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 813 CISS_UNLOCK_SCRATCH(sc, lock); 814 815 if (rv) 816 return rv; 817 818 CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n", 819 lmap->map[0].tgt, lmap->map[0].tgt2)); 820 821 return 0; 822 } 823 824 int 825 ciss_sync(struct ciss_softc *sc) 826 { 827 struct ciss_ccb *ccb; 828 struct ciss_cmd *cmd; 829 struct ciss_flush *flush; 830 ciss_lock_t lock; 831 int rv; 832 833 lock = CISS_LOCK_SCRATCH(sc); 834 flush = sc->scratch; 835 bzero(flush, sizeof(*flush)); 836 flush->flush = sc->sc_flush; 837 838 ccb = ciss_get_ccb(sc); 839 ccb->ccb_len = sizeof(*flush); 840 ccb->ccb_data = flush; 841 cmd = &ccb->ccb_cmd; 842 cmd->tgt = CISS_CMD_MODE_PERIPH; 843 cmd->tgt2 = 0; 844 cmd->cdblen = 10; 845 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 846 cmd->tmo = htole16(0); 847 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 848 cmd->cdb[0] = CISS_CMD_CTRL_SET; 849 cmd->cdb[6] = CISS_CMS_CTRL_FLUSH; 850 cmd->cdb[7] = sizeof(*flush) >> 8; /* biiiig endian */ 851 cmd->cdb[8] = sizeof(*flush) & 0xff; 852 853 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP); 854 CISS_UNLOCK_SCRATCH(sc, lock); 855 856 return rv; 857 } 858 859 int 860 ciss_scsi_raw_cmd(struct scsi_xfer *xs) /* TODO */ 861 { 862 struct scsi_link *link = xs->sc_link; 863 struct ciss_rawsoftc *rsc = link->adapter_softc; 864 struct ciss_softc *sc = rsc->sc_softc; 865 struct ciss_ccb *ccb; 866 struct ciss_cmd *cmd; 867 ciss_lock_t lock; 868 869 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd ")); 870 871 lock = CISS_LOCK(sc); 872 if (xs->cmdlen > CISS_MAX_CDB) { 873 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 874 bzero(&xs->sense, sizeof(xs->sense)); 875 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 876 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 877 xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */ 878 xs->error = XS_SENSE; 879 scsi_done(xs); 880 CISS_UNLOCK(sc, lock); 881 return (COMPLETE); 882 } 883 884 xs->error = XS_NOERROR; 885 886 /* TODO check this target has not yet employed w/ any volume */ 887 888 ccb = ciss_get_ccb(sc); 889 cmd = &ccb->ccb_cmd; 890 ccb->ccb_len = xs->datalen; 891 ccb->ccb_data = xs->data; 892 ccb->ccb_xs = xs; 893 894 895 896 cmd->cdblen = xs->cmdlen; 897 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 898 if (xs->flags & SCSI_DATA_IN) 899 cmd->flags |= CISS_CDB_IN; 900 else if (xs->flags & SCSI_DATA_OUT) 901 cmd->flags |= CISS_CDB_OUT; 902 cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000); 903 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 904 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB); 905 906 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 907 xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) { 908 xs->error = XS_DRIVER_STUFFUP; 909 scsi_done(xs); 910 CISS_UNLOCK(sc, lock); 911 return (COMPLETE); 912 } 913 914 CISS_UNLOCK(sc, lock); 915 return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED; 916 } 917 918 int 919 ciss_scsi_cmd(struct scsi_xfer *xs) 920 { 921 struct scsi_link *link = xs->sc_link; 922 struct ciss_softc *sc = link->adapter_softc; 923 u_int8_t target = link->target; 924 struct ciss_ccb *ccb; 925 struct ciss_cmd *cmd; 926 ciss_lock_t lock; 927 928 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd ")); 929 930 lock = CISS_LOCK(sc); 931 if (xs->cmdlen > CISS_MAX_CDB) { 932 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 933 bzero(&xs->sense, sizeof(xs->sense)); 934 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 935 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 936 xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */ 937 xs->error = XS_SENSE; 938 scsi_done(xs); 939 CISS_UNLOCK(sc, lock); 940 return (COMPLETE); 941 } 942 943 xs->error = XS_NOERROR; 944 945 /* XXX emulate SYNCHRONIZE_CACHE ??? */ 946 947 ccb = ciss_get_ccb(sc); 948 cmd = &ccb->ccb_cmd; 949 ccb->ccb_len = xs->datalen; 950 ccb->ccb_data = xs->data; 951 ccb->ccb_xs = xs; 952 cmd->tgt = CISS_CMD_MODE_LD | target; 953 cmd->tgt2 = 0; 954 cmd->cdblen = xs->cmdlen; 955 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 956 if (xs->flags & SCSI_DATA_IN) 957 cmd->flags |= CISS_CDB_IN; 958 else if (xs->flags & SCSI_DATA_OUT) 959 cmd->flags |= CISS_CDB_OUT; 960 cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000); 961 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 962 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB); 963 964 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 965 xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) { 966 xs->error = XS_DRIVER_STUFFUP; 967 scsi_done(xs); 968 CISS_UNLOCK(sc, lock); 969 return (COMPLETE); 970 } 971 972 CISS_UNLOCK(sc, lock); 973 return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED; 974 } 975 976 int 977 ciss_intr(void *v) 978 { 979 struct ciss_softc *sc = v; 980 struct ciss_ccb *ccb; 981 ciss_lock_t lock; 982 bus_size_t reg; 983 u_int32_t id; 984 int hit = 0; 985 986 CISS_DPRINTF(CISS_D_INTR, ("intr ")); 987 988 if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_ISR) & sc->iem)) 989 return 0; 990 991 lock = CISS_LOCK(sc); 992 993 if (sc->cfg.methods & CISS_METH_FIFO64) 994 reg = CISS_OUTQ64_HI; 995 else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) 996 reg = CISS_OUTQ64_LO; 997 else 998 reg = CISS_OUTQ; 999 while ((id = bus_space_read_4(sc->iot, sc->ioh, reg)) != 0xffffffff) { 1000 if (reg == CISS_OUTQ64_HI) 1001 id = bus_space_read_4(sc->iot, sc->ioh, 1002 CISS_OUTQ64_LO); 1003 else if (reg == CISS_OUTQ64_LO) 1004 (void)bus_space_read_4(sc->iot, sc->ioh, 1005 CISS_OUTQ64_HI); 1006 ccb = sc->ccbs + (id >> 2) * sc->ccblen; 1007 ccb->ccb_cmd.id = htole32(id); 1008 ccb->ccb_cmd.id_hi = htole32(0); /* ignore the upper 32bits */ 1009 if (ccb->ccb_state == CISS_CCB_POLL) { 1010 ccb->ccb_state = CISS_CCB_ONQ; 1011 wakeup(ccb); 1012 } else 1013 ciss_done(ccb); 1014 1015 hit = 1; 1016 } 1017 CISS_UNLOCK(sc, lock); 1018 1019 CISS_DPRINTF(CISS_D_INTR, ("exit ")); 1020 return hit; 1021 } 1022 1023 void 1024 ciss_heartbeat(void *v) 1025 { 1026 struct ciss_softc *sc = v; 1027 u_int32_t hb; 1028 1029 hb = bus_space_read_4(sc->iot, sc->cfg_ioh, 1030 sc->cfgoff + offsetof(struct ciss_config, heartbeat)); 1031 if (hb == sc->heartbeat) 1032 panic("%s: dead", sc->sc_dev.dv_xname); /* XXX reset! */ 1033 else 1034 sc->heartbeat = hb; 1035 1036 timeout_add_sec(&sc->sc_hb, 3); 1037 } 1038 1039 void 1040 ciss_kthread(void *v) 1041 { 1042 struct ciss_softc *sc = v; 1043 ciss_lock_t lock; 1044 1045 for (;;) { 1046 tsleep(sc, PRIBIO, sc->sc_dev.dv_xname, 0); 1047 1048 lock = CISS_LOCK(sc); 1049 1050 1051 1052 CISS_UNLOCK(sc, lock); 1053 } 1054 } 1055 1056 int 1057 ciss_scsi_ioctl(struct scsi_link *link, u_long cmd, 1058 caddr_t addr, int flag, struct proc *p) 1059 { 1060 #if NBIO > 0 1061 return ciss_ioctl(link->adapter_softc, cmd, addr); 1062 #else 1063 return ENOTTY; 1064 #endif 1065 } 1066 1067 #if NBIO > 0 1068 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 }; 1069 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 1070 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 1071 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 1072 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 1073 1074 int 1075 ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr) 1076 { 1077 struct ciss_softc *sc = (struct ciss_softc *)dev; 1078 struct bioc_inq *bi; 1079 struct bioc_vol *bv; 1080 struct bioc_disk *bd; 1081 struct bioc_blink *bb; 1082 /* struct bioc_alarm *ba; */ 1083 /* struct bioc_setstate *bss; */ 1084 struct ciss_ldid *ldid; 1085 struct ciss_ldstat *ldstat; 1086 struct ciss_pdid *pdid; 1087 struct ciss_blink *blink; 1088 struct ciss_ld *ldp; 1089 ciss_lock_t lock; 1090 u_int8_t drv; 1091 int ld, pd, error = 0; 1092 u_int blks; 1093 1094 if (!(sc->sc_flags & CISS_BIO)) 1095 return ENOTTY; 1096 1097 lock = CISS_LOCK(sc); 1098 switch (cmd) { 1099 case BIOCINQ: 1100 bi = (struct bioc_inq *)addr; 1101 strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev)); 1102 bi->bi_novol = sc->maxunits; 1103 bi->bi_nodisk = sc->ndrives; 1104 break; 1105 1106 case BIOCVOL: 1107 bv = (struct bioc_vol *)addr; 1108 if (bv->bv_volid > sc->maxunits) { 1109 error = EINVAL; 1110 break; 1111 } 1112 ldp = sc->sc_lds[bv->bv_volid]; 1113 if (!ldp) 1114 return EINVAL; 1115 ldid = sc->scratch; 1116 if ((error = ciss_ldid(sc, bv->bv_volid, ldid))) 1117 break; 1118 /* params 30:88:ff:00:00:00:00:00:00:00:00:00:00:00:20:00 */ 1119 bv->bv_status = BIOC_SVINVALID; 1120 blks = (u_int)letoh16(ldid->nblocks[1]) << 16 | 1121 letoh16(ldid->nblocks[0]); 1122 bv->bv_size = blks * (u_quad_t)letoh16(ldid->blksize); 1123 bv->bv_level = ciss_level[ldid->type]; 1124 bv->bv_nodisk = ldp->ndrives; 1125 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1126 strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor)); 1127 ldstat = sc->scratch; 1128 bzero(ldstat, sizeof(*ldstat)); 1129 if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat))) 1130 break; 1131 bv->bv_percent = -1; 1132 bv->bv_seconds = 0; 1133 if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0])) 1134 bv->bv_status = ciss_stat[ldstat->stat]; 1135 if (bv->bv_status == BIOC_SVREBUILD || 1136 bv->bv_status == BIOC_SVBUILDING) 1137 bv->bv_percent = (blks - 1138 (((u_int)ldstat->prog[3] << 24) | 1139 ((u_int)ldstat->prog[2] << 16) | 1140 ((u_int)ldstat->prog[1] << 8) | 1141 (u_int)ldstat->prog[0])) * 100ULL / blks; 1142 break; 1143 1144 case BIOCDISK: 1145 bd = (struct bioc_disk *)addr; 1146 if (bd->bd_volid > sc->maxunits) { 1147 error = EINVAL; 1148 break; 1149 } 1150 ldp = sc->sc_lds[bd->bd_volid]; 1151 if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) { 1152 error = EINVAL; 1153 break; 1154 } 1155 ldstat = sc->scratch; 1156 if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) 1157 break; 1158 bd->bd_status = -1; 1159 if (ldstat->stat == CISS_LD_REBLD && 1160 ldstat->bigrebuild == ldp->tgts[pd]) 1161 bd->bd_status = BIOC_SDREBUILD; 1162 if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT), 1163 ldstat->bigfailed)) { 1164 bd->bd_status = BIOC_SDFAILED; 1165 bd->bd_size = 0; 1166 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1167 sc->ndrives; 1168 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1169 bd->bd_lun = 0; 1170 bd->bd_vendor[0] = '\0'; 1171 bd->bd_serial[0] = '\0'; 1172 bd->bd_procdev[0] = '\0'; 1173 } else { 1174 pdid = sc->scratch; 1175 if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, 1176 SCSI_POLL))) 1177 break; 1178 if (bd->bd_status < 0) { 1179 if (pdid->config & CISS_PD_SPARE) 1180 bd->bd_status = BIOC_SDHOTSPARE; 1181 else if (pdid->present & CISS_PD_PRESENT) 1182 bd->bd_status = BIOC_SDONLINE; 1183 else 1184 bd->bd_status = BIOC_SDINVALID; 1185 } 1186 bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) * 1187 letoh16(pdid->blksz); 1188 bd->bd_channel = pdid->bus; 1189 bd->bd_target = pdid->target; 1190 bd->bd_lun = 0; 1191 strlcpy(bd->bd_vendor, pdid->model, 1192 sizeof(bd->bd_vendor)); 1193 strlcpy(bd->bd_serial, pdid->serial, 1194 sizeof(bd->bd_serial)); 1195 bd->bd_procdev[0] = '\0'; 1196 } 1197 break; 1198 1199 case BIOCBLINK: 1200 bb = (struct bioc_blink *)addr; 1201 blink = sc->scratch; 1202 error = EINVAL; 1203 /* XXX workaround completely dumb scsi addressing */ 1204 for (ld = 0; ld < sc->maxunits; ld++) { 1205 ldp = sc->sc_lds[ld]; 1206 if (!ldp) 1207 continue; 1208 if (sc->ndrives == 256) 1209 drv = bb->bb_target; 1210 else 1211 drv = CISS_BIGBIT + 1212 bb->bb_channel * sc->ndrives + 1213 bb->bb_target; 1214 for (pd = 0; pd < ldp->ndrives; pd++) 1215 if (ldp->tgts[pd] == drv) 1216 error = ciss_blink(sc, ld, pd, 1217 bb->bb_status, blink); 1218 } 1219 break; 1220 1221 case BIOCALARM: 1222 case BIOCSETSTATE: 1223 default: 1224 CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n", 1225 sc->sc_dev.dv_xname)); 1226 error = ENOTTY; 1227 } 1228 CISS_UNLOCK(sc, lock); 1229 1230 return error; 1231 } 1232 1233 #ifndef SMALL_KERNEL 1234 void 1235 ciss_sensors(void *v) 1236 { 1237 struct ciss_softc *sc = v; 1238 struct ciss_ldstat *ldstat; 1239 int i, error; 1240 1241 for (i = 0; i < sc->maxunits; i++) { 1242 ldstat = sc->scratch; 1243 if ((error = ciss_ldstat(sc, i, ldstat))) { 1244 sc->sensors[i].value = 0; 1245 sc->sensors[i].status = SENSOR_S_UNKNOWN; 1246 continue; 1247 } 1248 1249 switch (ldstat->stat) { 1250 case CISS_LD_OK: 1251 sc->sensors[i].value = SENSOR_DRIVE_ONLINE; 1252 sc->sensors[i].status = SENSOR_S_OK; 1253 break; 1254 1255 case CISS_LD_DEGRAD: 1256 sc->sensors[i].value = SENSOR_DRIVE_PFAIL; 1257 sc->sensors[i].status = SENSOR_S_WARN; 1258 break; 1259 1260 case CISS_LD_EXPND: 1261 case CISS_LD_QEXPND: 1262 case CISS_LD_RBLDRD: 1263 case CISS_LD_REBLD: 1264 sc->sensors[i].value = SENSOR_DRIVE_REBUILD; 1265 sc->sensors[i].status = SENSOR_S_WARN; 1266 break; 1267 1268 case CISS_LD_NORDY: 1269 case CISS_LD_PDINV: 1270 case CISS_LD_PDUNC: 1271 case CISS_LD_FAILED: 1272 case CISS_LD_UNCONF: 1273 sc->sensors[i].value = SENSOR_DRIVE_FAIL; 1274 sc->sensors[i].status = SENSOR_S_CRIT; 1275 break; 1276 1277 default: 1278 sc->sensors[i].value = 0; 1279 sc->sensors[i].status = SENSOR_S_UNKNOWN; 1280 } 1281 } 1282 } 1283 #endif /* SMALL_KERNEL */ 1284 1285 int 1286 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id) 1287 { 1288 struct ciss_ccb *ccb; 1289 struct ciss_cmd *cmd; 1290 1291 ccb = ciss_get_ccb(sc); 1292 if (ccb == NULL) 1293 return ENOMEM; 1294 ccb->ccb_len = sizeof(*id); 1295 ccb->ccb_data = id; 1296 ccb->ccb_xs = NULL; 1297 cmd = &ccb->ccb_cmd; 1298 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1299 cmd->tgt2 = 0; 1300 cmd->cdblen = 10; 1301 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 1302 cmd->tmo = htole16(0); 1303 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1304 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1305 cmd->cdb[5] = target; 1306 cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT; 1307 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 1308 cmd->cdb[8] = sizeof(*id) & 0xff; 1309 1310 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1311 } 1312 1313 int 1314 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat) 1315 { 1316 struct ciss_ccb *ccb; 1317 struct ciss_cmd *cmd; 1318 1319 ccb = ciss_get_ccb(sc); 1320 if (ccb == NULL) 1321 return ENOMEM; 1322 ccb->ccb_len = sizeof(*stat); 1323 ccb->ccb_data = stat; 1324 ccb->ccb_xs = NULL; 1325 cmd = &ccb->ccb_cmd; 1326 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1327 cmd->tgt2 = 0; 1328 cmd->cdblen = 10; 1329 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 1330 cmd->tmo = htole16(0); 1331 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1332 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1333 cmd->cdb[5] = target; 1334 cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT; 1335 cmd->cdb[7] = sizeof(*stat) >> 8; /* biiiig endian */ 1336 cmd->cdb[8] = sizeof(*stat) & 0xff; 1337 1338 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1339 } 1340 1341 int 1342 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait) 1343 { 1344 struct ciss_ccb *ccb; 1345 struct ciss_cmd *cmd; 1346 1347 ccb = ciss_get_ccb(sc); 1348 if (ccb == NULL) 1349 return ENOMEM; 1350 ccb->ccb_len = sizeof(*id); 1351 ccb->ccb_data = id; 1352 ccb->ccb_xs = NULL; 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_IN; 1358 cmd->tmo = htole16(0); 1359 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1360 cmd->cdb[0] = CISS_CMD_CTRL_GET; 1361 cmd->cdb[2] = drv; 1362 cmd->cdb[6] = CISS_CMS_CTRL_PDID; 1363 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 1364 cmd->cdb[8] = sizeof(*id) & 0xff; 1365 1366 return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait); 1367 } 1368 1369 1370 struct ciss_ld * 1371 ciss_pdscan(struct ciss_softc *sc, int ld) 1372 { 1373 struct ciss_pdid *pdid; 1374 struct ciss_ld *ldp; 1375 u_int8_t drv, buf[128]; 1376 int i, j, k = 0; 1377 1378 pdid = sc->scratch; 1379 if (sc->ndrives == 256) { 1380 for (i = 0; i < CISS_BIGBIT; i++) 1381 if (!ciss_pdid(sc, i, pdid, SCSI_NOSLEEP|SCSI_POLL) && 1382 (pdid->present & CISS_PD_PRESENT)) 1383 buf[k++] = i; 1384 } else 1385 for (i = 0; i < sc->nbus; i++) 1386 for (j = 0; j < sc->ndrives; j++) { 1387 drv = CISS_BIGBIT + i * sc->ndrives + j; 1388 if (!ciss_pdid(sc, drv, pdid, 1389 SCSI_NOSLEEP|SCSI_POLL)) 1390 buf[k++] = drv; 1391 } 1392 1393 if (!k) 1394 return NULL; 1395 1396 ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT); 1397 if (!ldp) 1398 return NULL; 1399 1400 bzero(&ldp->bling, sizeof(ldp->bling)); 1401 ldp->ndrives = k; 1402 bcopy(buf, ldp->tgts, k); 1403 return ldp; 1404 } 1405 1406 int 1407 ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat, 1408 struct ciss_blink *blink) 1409 { 1410 struct ciss_ccb *ccb; 1411 struct ciss_cmd *cmd; 1412 struct ciss_ld *ldp; 1413 1414 if (ld > sc->maxunits) 1415 return EINVAL; 1416 1417 ldp = sc->sc_lds[ld]; 1418 if (!ldp || pd > ldp->ndrives) 1419 return EINVAL; 1420 1421 ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 : 1422 CISS_BLINK_ALL; 1423 bcopy(&ldp->bling, blink, sizeof(*blink)); 1424 1425 ccb = ciss_get_ccb(sc); 1426 if (ccb == NULL) 1427 return ENOMEM; 1428 ccb->ccb_len = sizeof(*blink); 1429 ccb->ccb_data = blink; 1430 ccb->ccb_xs = NULL; 1431 cmd = &ccb->ccb_cmd; 1432 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1433 cmd->tgt2 = 0; 1434 cmd->cdblen = 10; 1435 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 1436 cmd->tmo = htole16(0); 1437 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1438 cmd->cdb[0] = CISS_CMD_CTRL_SET; 1439 cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK; 1440 cmd->cdb[7] = sizeof(*blink) >> 8; /* biiiig endian */ 1441 cmd->cdb[8] = sizeof(*blink) & 0xff; 1442 1443 return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL); 1444 } 1445 #endif 1446