1 /* $NetBSD: ciss.c,v 1.14 2008/09/04 19:03:14 he Exp $ */ 2 /* $OpenBSD: ciss.c,v 1.14 2006/03/13 16:02:23 mickey Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Michael Shalayeff 6 * All rights reserved. 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 17 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.14 2008/09/04 19:03:14 he Exp $"); 23 24 #include "bio.h" 25 26 /* #define CISS_DEBUG */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/buf.h> 31 #include <sys/ioctl.h> 32 #include <sys/device.h> 33 #include <sys/kernel.h> 34 #include <sys/malloc.h> 35 #include <sys/proc.h> 36 37 #include <uvm/uvm_extern.h> 38 39 #include <sys/bus.h> 40 41 #include <dev/scsipi/scsi_all.h> 42 #include <dev/scsipi/scsi_disk.h> 43 #include <dev/scsipi/scsiconf.h> 44 45 #include <dev/ic/cissreg.h> 46 #include <dev/ic/cissvar.h> 47 48 #if NBIO > 0 49 #include <dev/biovar.h> 50 #endif /* NBIO > 0 */ 51 52 #ifdef CISS_DEBUG 53 #define CISS_DPRINTF(m,a) if (ciss_debug & (m)) printf a 54 #define CISS_D_CMD 0x0001 55 #define CISS_D_INTR 0x0002 56 #define CISS_D_MISC 0x0004 57 #define CISS_D_DMA 0x0008 58 #define CISS_D_IOCTL 0x0010 59 #define CISS_D_ERR 0x0020 60 int ciss_debug = 0 61 | CISS_D_CMD 62 | CISS_D_INTR 63 | CISS_D_MISC 64 | CISS_D_DMA 65 | CISS_D_IOCTL 66 | CISS_D_ERR 67 ; 68 #else 69 #define CISS_DPRINTF(m,a) /* m, a */ 70 #endif 71 72 static void ciss_scsi_cmd(struct scsipi_channel *chan, 73 scsipi_adapter_req_t req, void *arg); 74 static int ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd, 75 void *addr, int flag, struct proc *p); 76 static void cissminphys(struct buf *bp); 77 78 #if 0 79 static void ciss_scsi_raw_cmd(struct scsipi_channel *chan, 80 scsipi_adapter_req_t req, void *arg); 81 #endif 82 83 static int ciss_sync(struct ciss_softc *sc); 84 static void ciss_heartbeat(void *v); 85 static void ciss_shutdown(void *v); 86 87 static struct ciss_ccb *ciss_get_ccb(struct ciss_softc *sc); 88 static void ciss_put_ccb(struct ciss_ccb *ccb); 89 static int ciss_cmd(struct ciss_ccb *ccb, int flags, int wait); 90 static int ciss_done(struct ciss_ccb *ccb); 91 static int ciss_error(struct ciss_ccb *ccb); 92 struct ciss_ld *ciss_pdscan(struct ciss_softc *sc, int ld); 93 static int ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq); 94 int ciss_ldid(struct ciss_softc *, int, struct ciss_ldid *); 95 int ciss_ldstat(struct ciss_softc *, int, struct ciss_ldstat *); 96 static int ciss_ldmap(struct ciss_softc *sc); 97 int ciss_pdid(struct ciss_softc *, u_int8_t, struct ciss_pdid *, int); 98 99 #if NBIO > 0 100 int ciss_ioctl(struct device *, u_long, void *); 101 int ciss_ioctl_vol(struct ciss_softc *, struct bioc_vol *); 102 int ciss_blink(struct ciss_softc *, int, int, int, struct ciss_blink *); 103 int ciss_create_sensors(struct ciss_softc *); 104 void ciss_sensor_refresh(struct sysmon_envsys *, envsys_data_t *); 105 #endif /* NBIO > 0 */ 106 107 static struct ciss_ccb * 108 ciss_get_ccb(struct ciss_softc *sc) 109 { 110 struct ciss_ccb *ccb; 111 112 mutex_enter(&sc->sc_mutex); 113 if ((ccb = TAILQ_LAST(&sc->sc_free_ccb, ciss_queue_head))) { 114 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link); 115 ccb->ccb_state = CISS_CCB_READY; 116 } 117 mutex_exit(&sc->sc_mutex); 118 return ccb; 119 } 120 121 static void 122 ciss_put_ccb(struct ciss_ccb *ccb) 123 { 124 struct ciss_softc *sc = ccb->ccb_sc; 125 126 ccb->ccb_state = CISS_CCB_FREE; 127 mutex_enter(&sc->sc_mutex); 128 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link); 129 mutex_exit(&sc->sc_mutex); 130 } 131 132 int 133 ciss_attach(struct ciss_softc *sc) 134 { 135 struct ciss_ccb *ccb; 136 struct ciss_cmd *cmd; 137 struct ciss_inquiry *inq; 138 bus_dma_segment_t seg[1]; 139 int error, i, total, rseg, maxfer; 140 paddr_t pa; 141 142 bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, 143 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 144 145 if (sc->cfg.signature != CISS_SIGNATURE) { 146 printf(": bad sign 0x%08x\n", sc->cfg.signature); 147 return -1; 148 } 149 150 if (!(sc->cfg.methods & CISS_METH_SIMPL)) { 151 printf(": not simple 0x%08x\n", sc->cfg.methods); 152 return -1; 153 } 154 155 sc->cfg.rmethod = CISS_METH_SIMPL; 156 sc->cfg.paddr_lim = 0; /* 32bit addrs */ 157 sc->cfg.int_delay = 0; /* disable coalescing */ 158 sc->cfg.int_count = 0; 159 strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname)); 160 sc->cfg.driverf |= CISS_DRV_PRF; /* enable prefetch */ 161 if (!sc->cfg.maxsg) 162 sc->cfg.maxsg = MAXPHYS / PAGE_SIZE + 1; 163 164 bus_space_write_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, 165 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 166 bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg), 167 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); 168 169 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IDB, CISS_IDB_CFG); 170 bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4, 171 BUS_SPACE_BARRIER_WRITE); 172 for (i = 1000; i--; DELAY(1000)) { 173 /* XXX maybe IDB is really 64bit? - hp dl380 needs this */ 174 (void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB + 4); 175 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG)) 176 break; 177 bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4, 178 BUS_SPACE_BARRIER_READ); 179 } 180 181 if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG) { 182 printf(": cannot set config\n"); 183 return -1; 184 } 185 186 bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, 187 (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4); 188 189 if (!(sc->cfg.amethod & CISS_METH_SIMPL)) { 190 printf(": cannot simplify 0x%08x\n", sc->cfg.amethod); 191 return -1; 192 } 193 194 /* i'm ready for you and i hope you're ready for me */ 195 for (i = 30000; i--; DELAY(1000)) { 196 if (bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff + 197 offsetof(struct ciss_config, amethod)) & CISS_METH_READY) 198 break; 199 bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff + 200 offsetof(struct ciss_config, amethod), 4, 201 BUS_SPACE_BARRIER_READ); 202 } 203 204 if (!(bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff + 205 offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) { 206 printf(": she never came ready for me 0x%08x\n", 207 sc->cfg.amethod); 208 return -1; 209 } 210 211 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); 212 mutex_init(&sc->sc_mutex_scratch, MUTEX_DEFAULT, IPL_VM); 213 cv_init(&sc->sc_condvar, "ciss_cmd"); 214 sc->maxcmd = sc->cfg.maxcmd; 215 sc->maxsg = sc->cfg.maxsg; 216 if (sc->maxsg > MAXPHYS / PAGE_SIZE + 1) 217 sc->maxsg = MAXPHYS / PAGE_SIZE + 1; 218 i = sizeof(struct ciss_ccb) + 219 sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1); 220 for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1); 221 222 total = sc->ccblen * sc->maxcmd; 223 if ((error = bus_dmamem_alloc(sc->sc_dmat, total, PAGE_SIZE, 0, 224 sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT))) { 225 printf(": cannot allocate CCBs (%d)\n", error); 226 return -1; 227 } 228 229 if ((error = bus_dmamem_map(sc->sc_dmat, sc->cmdseg, rseg, total, 230 (void **)&sc->ccbs, BUS_DMA_NOWAIT))) { 231 printf(": cannot map CCBs (%d)\n", error); 232 return -1; 233 } 234 bzero(sc->ccbs, total); 235 236 if ((error = bus_dmamap_create(sc->sc_dmat, total, 1, 237 total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) { 238 printf(": cannot create CCBs dmamap (%d)\n", error); 239 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 240 return -1; 241 } 242 243 if ((error = bus_dmamap_load(sc->sc_dmat, sc->cmdmap, sc->ccbs, total, 244 NULL, BUS_DMA_NOWAIT))) { 245 printf(": cannot load CCBs dmamap (%d)\n", error); 246 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 247 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 248 return -1; 249 } 250 251 TAILQ_INIT(&sc->sc_ccbq); 252 TAILQ_INIT(&sc->sc_ccbdone); 253 TAILQ_INIT(&sc->sc_free_ccb); 254 255 maxfer = sc->maxsg * PAGE_SIZE; 256 for (i = 0; total > 0 && i < sc->maxcmd; i++, total -= sc->ccblen) { 257 ccb = (struct ciss_ccb *) ((char *)sc->ccbs + i * sc->ccblen); 258 cmd = &ccb->ccb_cmd; 259 pa = sc->cmdseg[0].ds_addr + i * sc->ccblen; 260 261 ccb->ccb_sc = sc; 262 ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd); 263 ccb->ccb_state = CISS_CCB_FREE; 264 265 cmd->id = htole32(i << 2); 266 cmd->id_hi = htole32(0); 267 cmd->sgin = sc->maxsg; 268 cmd->sglen = htole16((u_int16_t)cmd->sgin); 269 cmd->err_len = htole32(sizeof(ccb->ccb_err)); 270 pa += offsetof(struct ciss_ccb, ccb_err); 271 cmd->err_pa = htole64((u_int64_t)pa); 272 273 if ((error = bus_dmamap_create(sc->sc_dmat, maxfer, sc->maxsg, 274 maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 275 &ccb->ccb_dmamap))) 276 break; 277 278 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link); 279 } 280 281 if (i < sc->maxcmd) { 282 printf(": cannot create ccb#%d dmamap (%d)\n", i, error); 283 if (i == 0) { 284 /* TODO leaking cmd's dmamaps and shitz */ 285 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 286 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 287 return -1; 288 } 289 } 290 291 if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, 292 seg, 1, &rseg, BUS_DMA_NOWAIT))) { 293 printf(": cannot allocate scratch buffer (%d)\n", error); 294 return -1; 295 } 296 297 if ((error = bus_dmamem_map(sc->sc_dmat, seg, rseg, PAGE_SIZE, 298 (void **)&sc->scratch, BUS_DMA_NOWAIT))) { 299 printf(": cannot map scratch buffer (%d)\n", error); 300 return -1; 301 } 302 bzero(sc->scratch, PAGE_SIZE); 303 sc->sc_waitflag = XS_CTL_NOSLEEP; /* can't sleep yet */ 304 305 mutex_enter(&sc->sc_mutex_scratch); /* is this really needed? */ 306 inq = sc->scratch; 307 if (ciss_inq(sc, inq)) { 308 printf(": adapter inquiry failed\n"); 309 mutex_exit(&sc->sc_mutex_scratch); 310 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 311 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 312 return -1; 313 } 314 315 if (!(inq->flags & CISS_INQ_BIGMAP)) { 316 printf(": big map is not supported, flags=0x%x\n", 317 inq->flags); 318 mutex_exit(&sc->sc_mutex_scratch); 319 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 320 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 321 return -1; 322 } 323 324 sc->maxunits = inq->numld; 325 sc->nbus = inq->nscsi_bus; 326 sc->ndrives = inq->buswidth ? inq->buswidth : 256; 327 printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s\n", 328 inq->numld, inq->numld == 1? "" : "s", 329 inq->hw_rev, inq->fw_running, inq->fw_stored); 330 331 mutex_exit(&sc->sc_mutex_scratch); 332 333 callout_init(&sc->sc_hb, 0); 334 callout_setfunc(&sc->sc_hb, ciss_heartbeat, sc); 335 callout_schedule(&sc->sc_hb, hz * 3); 336 337 /* map LDs */ 338 if (ciss_ldmap(sc)) { 339 aprint_error_dev(&sc->sc_dev, "adapter LD map failed\n"); 340 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 341 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 342 return -1; 343 } 344 345 if (!(sc->sc_lds = malloc(sc->maxunits * sizeof(*sc->sc_lds), 346 M_DEVBUF, M_NOWAIT))) { 347 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 348 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 349 return -1; 350 } 351 bzero(sc->sc_lds, sc->maxunits * sizeof(*sc->sc_lds)); 352 353 sc->sc_flush = CISS_FLUSH_ENABLE; 354 if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) { 355 printf(": unable to establish shutdown hook\n"); 356 bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1); 357 bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap); 358 return -1; 359 } 360 361 sc->sc_channel.chan_adapter = &sc->sc_adapter; 362 sc->sc_channel.chan_bustype = &scsi_bustype; 363 sc->sc_channel.chan_channel = 0; 364 sc->sc_channel.chan_ntargets = sc->maxunits; 365 sc->sc_channel.chan_nluns = 1; /* ciss doesn't really have SCSI luns */ 366 sc->sc_channel.chan_openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1); 367 #if NBIO > 0 368 /* XXX Reserve some ccb's for sensor and bioctl. */ 369 if (sc->sc_channel.chan_openings > 2) 370 sc->sc_channel.chan_openings -= 2; 371 #endif 372 sc->sc_channel.chan_flags = 0; 373 sc->sc_channel.chan_id = sc->maxunits; 374 375 sc->sc_adapter.adapt_dev = (struct device *) sc; 376 sc->sc_adapter.adapt_openings = sc->sc_channel.chan_openings; 377 sc->sc_adapter.adapt_max_periph = sc->maxunits; 378 sc->sc_adapter.adapt_request = ciss_scsi_cmd; 379 sc->sc_adapter.adapt_minphys = cissminphys; 380 sc->sc_adapter.adapt_ioctl = ciss_scsi_ioctl; 381 sc->sc_adapter.adapt_nchannels = 1; 382 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint); 383 384 #if 0 385 sc->sc_link_raw.adapter_softc = sc; 386 sc->sc_link.openings = sc->sc_channel.chan_openings; 387 sc->sc_link_raw.adapter = &ciss_raw_switch; 388 sc->sc_link_raw.adapter_target = sc->ndrives; 389 sc->sc_link_raw.adapter_buswidth = sc->ndrives; 390 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint); 391 #endif 392 393 #if NBIO > 0 394 /* now map all the physdevs into their lds */ 395 /* XXX currently we assign all of them into ld0 */ 396 for (i = 0; i < sc->maxunits && i < 1; i++) 397 if (!(sc->sc_lds[i] = ciss_pdscan(sc, i))) { 398 sc->sc_waitflag = 0; /* we can sleep now */ 399 return 0; 400 } 401 402 if (bio_register(&sc->sc_dev, ciss_ioctl) != 0) 403 aprint_error_dev(&sc->sc_dev, "controller registration failed"); 404 else 405 sc->sc_ioctl = ciss_ioctl; 406 if (ciss_create_sensors(sc) != 0) 407 aprint_error_dev(&sc->sc_dev, "unable to create sensors"); 408 #endif 409 sc->sc_waitflag = 0; /* we can sleep now */ 410 411 return 0; 412 } 413 414 static void 415 ciss_shutdown(void *v) 416 { 417 struct ciss_softc *sc = v; 418 419 sc->sc_flush = CISS_FLUSH_DISABLE; 420 /* timeout_del(&sc->sc_hb); */ 421 ciss_sync(sc); 422 } 423 424 static void 425 cissminphys(struct buf *bp) 426 { 427 #if 0 /* TOSO */ 428 #define CISS_MAXFER (PAGE_SIZE * (sc->maxsg + 1)) 429 if (bp->b_bcount > CISS_MAXFER) 430 bp->b_bcount = CISS_MAXFER; 431 #endif 432 minphys(bp); 433 } 434 435 /* 436 * submit a command and optionally wait for completition. 437 * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request 438 * to wait (XS_CTL_POLL) and to allow tsleep() (!XS_CTL_NOSLEEP) 439 * instead of busy loop waiting 440 */ 441 static int 442 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) 443 { 444 struct ciss_softc *sc = ccb->ccb_sc; 445 struct ciss_cmd *cmd = &ccb->ccb_cmd; 446 struct ciss_ccb *ccb1; 447 bus_dmamap_t dmap = ccb->ccb_dmamap; 448 u_int32_t id; 449 int i, tohz, error = 0; 450 451 if (ccb->ccb_state != CISS_CCB_READY) { 452 printf("%s: ccb %d not ready state=0x%x\n", device_xname(&sc->sc_dev), 453 cmd->id, ccb->ccb_state); 454 return (EINVAL); 455 } 456 457 if (ccb->ccb_data) { 458 bus_dma_segment_t *sgd; 459 460 if ((error = bus_dmamap_load(sc->sc_dmat, dmap, ccb->ccb_data, 461 ccb->ccb_len, NULL, flags))) { 462 if (error == EFBIG) 463 printf("more than %d dma segs\n", sc->maxsg); 464 else 465 printf("error %d loading dma map\n", error); 466 ciss_put_ccb(ccb); 467 return (error); 468 } 469 cmd->sgin = dmap->dm_nsegs; 470 471 sgd = dmap->dm_segs; 472 CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%lu", 473 ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len)); 474 475 for (i = 0; i < dmap->dm_nsegs; sgd++, i++) { 476 cmd->sgl[i].addr_lo = htole32(sgd->ds_addr); 477 cmd->sgl[i].addr_hi = 478 htole32((u_int64_t)sgd->ds_addr >> 32); 479 cmd->sgl[i].len = htole32(sgd->ds_len); 480 cmd->sgl[i].flags = htole32(0); 481 if (i) { 482 CISS_DPRINTF(CISS_D_DMA, 483 (",0x%lx/%lu", sgd->ds_addr, sgd->ds_len)); 484 } 485 } 486 487 CISS_DPRINTF(CISS_D_DMA, ("> ")); 488 489 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 490 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 491 } else 492 cmd->sgin = 0; 493 cmd->sglen = htole16((u_int16_t)cmd->sgin); 494 bzero(&ccb->ccb_err, sizeof(ccb->ccb_err)); 495 496 bus_dmamap_sync(sc->sc_dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize, 497 BUS_DMASYNC_PREWRITE); 498 499 if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP)) 500 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR, 501 bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) | sc->iem); 502 503 mutex_enter(&sc->sc_mutex); 504 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link); 505 mutex_exit(&sc->sc_mutex); 506 ccb->ccb_state = CISS_CCB_ONQ; 507 CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); 508 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa); 509 510 if (wait & XS_CTL_POLL) { 511 int etick; 512 CISS_DPRINTF(CISS_D_CMD, ("waiting ")); 513 514 i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000; 515 tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000); 516 if (tohz == 0) 517 tohz = 1; 518 for (i *= 100, etick = tick + tohz; i--; ) { 519 if (!(wait & XS_CTL_NOSLEEP)) { 520 ccb->ccb_state = CISS_CCB_POLL; 521 CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz)); 522 mutex_enter(&sc->sc_mutex); 523 if (cv_timedwait(&sc->sc_condvar, 524 &sc->sc_mutex, tohz) == EWOULDBLOCK) { 525 mutex_exit(&sc->sc_mutex); 526 break; 527 } 528 mutex_exit(&sc->sc_mutex); 529 if (ccb->ccb_state != CISS_CCB_ONQ) { 530 tohz = etick - tick; 531 if (tohz <= 0) 532 break; 533 CISS_DPRINTF(CISS_D_CMD, ("T")); 534 continue; 535 } 536 ccb1 = ccb; 537 } else { 538 DELAY(10); 539 540 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, 541 CISS_ISR) & sc->iem)) { 542 CISS_DPRINTF(CISS_D_CMD, ("N")); 543 continue; 544 } 545 546 if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 547 CISS_OUTQ)) == 0xffffffff) { 548 CISS_DPRINTF(CISS_D_CMD, ("Q")); 549 continue; 550 } 551 552 CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); 553 ccb1 = (struct ciss_ccb *) 554 ((char *)sc->ccbs + (id >> 2) * sc->ccblen); 555 ccb1->ccb_cmd.id = htole32(id); 556 } 557 558 error = ciss_done(ccb1); 559 if (ccb1 == ccb) 560 break; 561 } 562 563 /* if never got a chance to be done above... */ 564 if (ccb->ccb_state != CISS_CCB_FREE) { 565 ccb->ccb_err.cmd_stat = CISS_ERR_TMO; 566 error = ciss_done(ccb); 567 } 568 569 CISS_DPRINTF(CISS_D_CMD, ("done %d:%d", 570 ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat)); 571 } 572 573 if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP)) 574 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR, 575 bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) & ~sc->iem); 576 577 return (error); 578 } 579 580 static int 581 ciss_done(struct ciss_ccb *ccb) 582 { 583 struct ciss_softc *sc = ccb->ccb_sc; 584 struct scsipi_xfer *xs = ccb->ccb_xs; 585 struct ciss_cmd *cmd; 586 int error = 0; 587 588 CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb)); 589 590 if (ccb->ccb_state != CISS_CCB_ONQ) { 591 printf("%s: unqueued ccb %p ready, state=0x%x\n", 592 device_xname(&sc->sc_dev), ccb, ccb->ccb_state); 593 return 1; 594 } 595 596 ccb->ccb_state = CISS_CCB_READY; 597 mutex_enter(&sc->sc_mutex); 598 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link); 599 mutex_exit(&sc->sc_mutex); 600 601 if (ccb->ccb_cmd.id & CISS_CMD_ERR) 602 error = ciss_error(ccb); 603 604 cmd = &ccb->ccb_cmd; 605 if (ccb->ccb_data) { 606 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 607 ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ? 608 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 609 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); 610 ccb->ccb_xs = NULL; 611 ccb->ccb_data = NULL; 612 } 613 614 ciss_put_ccb(ccb); 615 616 if (xs) { 617 xs->resid = 0; 618 CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs)); 619 scsipi_done(xs); 620 } 621 622 return error; 623 } 624 625 static int 626 ciss_error(struct ciss_ccb *ccb) 627 { 628 struct ciss_softc *sc = ccb->ccb_sc; 629 struct ciss_error *err = &ccb->ccb_err; 630 struct scsipi_xfer *xs = ccb->ccb_xs; 631 int rv; 632 633 switch ((rv = le16toh(err->cmd_stat))) { 634 case CISS_ERR_OK: 635 break; 636 637 case CISS_ERR_INVCMD: 638 printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n", 639 device_xname(&sc->sc_dev), ccb->ccb_cmd.id, 640 err->err_info, err->err_type[3], err->err_type[2]); 641 if (xs) { 642 bzero(&xs->sense, sizeof(xs->sense)); 643 xs->sense.scsi_sense.response_code = 644 SSD_RCODE_CURRENT | SSD_RCODE_VALID; 645 xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST; 646 xs->sense.scsi_sense.asc = 0x24; /* ill field */ 647 xs->sense.scsi_sense.ascq = 0x0; 648 xs->error = XS_SENSE; 649 } 650 break; 651 652 case CISS_ERR_TMO: 653 xs->error = XS_TIMEOUT; 654 break; 655 656 case CISS_ERR_UNRUN: 657 /* Underrun */ 658 xs->resid = le32toh(err->resid); 659 CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ", 660 xs->resid)); 661 break; 662 default: 663 if (xs) { 664 CISS_DPRINTF(CISS_D_CMD, ("scsi_stat=%x ", err->scsi_stat)); 665 switch (err->scsi_stat) { 666 case SCSI_CHECK: 667 xs->error = XS_SENSE; 668 bcopy(&err->sense[0], &xs->sense, 669 sizeof(xs->sense)); 670 CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ", 671 err->sense[0], err->sense[1], err->sense[2], err->sense[3])); 672 break; 673 674 case XS_BUSY: 675 xs->error = XS_BUSY; 676 break; 677 678 default: 679 CISS_DPRINTF(CISS_D_ERR, ("%s: " 680 "cmd_stat=%x scsi_stat=0x%x resid=0x%x\n", 681 device_xname(&sc->sc_dev), rv, err->scsi_stat, 682 le32toh(err->resid))); 683 printf("ciss driver stuffup in %s:%d: %s()\n", 684 __FILE__, __LINE__, __func__); 685 xs->error = XS_DRIVER_STUFFUP; 686 break; 687 } 688 xs->resid = le32toh(err->resid); 689 } 690 } 691 ccb->ccb_cmd.id &= htole32(~3); 692 693 return rv; 694 } 695 696 static int 697 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq) 698 { 699 struct ciss_ccb *ccb; 700 struct ciss_cmd *cmd; 701 702 ccb = ciss_get_ccb(sc); 703 ccb->ccb_len = sizeof(*inq); 704 ccb->ccb_data = inq; 705 ccb->ccb_xs = NULL; 706 cmd = &ccb->ccb_cmd; 707 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 708 cmd->tgt2 = 0; 709 cmd->cdblen = 10; 710 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 711 cmd->tmo = htole16(0); 712 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 713 cmd->cdb[0] = CISS_CMD_CTRL_GET; 714 cmd->cdb[6] = CISS_CMS_CTRL_CTRL; 715 cmd->cdb[7] = sizeof(*inq) >> 8; /* biiiig endian */ 716 cmd->cdb[8] = sizeof(*inq) & 0xff; 717 718 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 719 } 720 721 static int 722 ciss_ldmap(struct ciss_softc *sc) 723 { 724 struct ciss_ccb *ccb; 725 struct ciss_cmd *cmd; 726 struct ciss_ldmap *lmap; 727 int total, rv; 728 729 mutex_enter(&sc->sc_mutex_scratch); 730 lmap = sc->scratch; 731 lmap->size = htobe32(sc->maxunits * sizeof(lmap->map)); 732 total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map); 733 734 ccb = ciss_get_ccb(sc); 735 ccb->ccb_len = total; 736 ccb->ccb_data = lmap; 737 ccb->ccb_xs = NULL; 738 cmd = &ccb->ccb_cmd; 739 cmd->tgt = CISS_CMD_MODE_PERIPH; 740 cmd->tgt2 = 0; 741 cmd->cdblen = 12; 742 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 743 cmd->tmo = htole16(30); 744 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 745 cmd->cdb[0] = CISS_CMD_LDMAP; 746 cmd->cdb[8] = total >> 8; /* biiiig endian */ 747 cmd->cdb[9] = total & 0xff; 748 749 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 750 751 if (rv) { 752 mutex_exit(&sc->sc_mutex_scratch); 753 return rv; 754 } 755 756 CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n", 757 lmap->map[0].tgt, lmap->map[0].tgt2)); 758 759 mutex_exit(&sc->sc_mutex_scratch); 760 return 0; 761 } 762 763 static int 764 ciss_sync(struct ciss_softc *sc) 765 { 766 struct ciss_ccb *ccb; 767 struct ciss_cmd *cmd; 768 struct ciss_flush *flush; 769 int rv; 770 771 mutex_enter(&sc->sc_mutex_scratch); 772 flush = sc->scratch; 773 bzero(flush, sizeof(*flush)); 774 flush->flush = sc->sc_flush; 775 776 ccb = ciss_get_ccb(sc); 777 ccb->ccb_len = sizeof(*flush); 778 ccb->ccb_data = flush; 779 ccb->ccb_xs = NULL; 780 cmd = &ccb->ccb_cmd; 781 cmd->tgt = CISS_CMD_MODE_PERIPH; 782 cmd->tgt2 = 0; 783 cmd->cdblen = 10; 784 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 785 cmd->tmo = 0; 786 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 787 cmd->cdb[0] = CISS_CMD_CTRL_SET; 788 cmd->cdb[6] = CISS_CMS_CTRL_FLUSH; 789 cmd->cdb[7] = sizeof(*flush) >> 8; /* biiiig endian */ 790 cmd->cdb[8] = sizeof(*flush) & 0xff; 791 792 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 793 mutex_exit(&sc->sc_mutex_scratch); 794 795 return rv; 796 } 797 798 int 799 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id) 800 { 801 struct ciss_ccb *ccb; 802 struct ciss_cmd *cmd; 803 804 ccb = ciss_get_ccb(sc); 805 if (ccb == NULL) 806 return ENOMEM; 807 ccb->ccb_len = sizeof(*id); 808 ccb->ccb_data = id; 809 ccb->ccb_xs = NULL; 810 cmd = &ccb->ccb_cmd; 811 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 812 cmd->tgt2 = 0; 813 cmd->cdblen = 10; 814 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 815 cmd->tmo = htole16(0); 816 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 817 cmd->cdb[0] = CISS_CMD_CTRL_GET; 818 cmd->cdb[1] = target; 819 cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT; 820 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 821 cmd->cdb[8] = sizeof(*id) & 0xff; 822 823 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag); 824 } 825 826 int 827 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat) 828 { 829 struct ciss_ccb *ccb; 830 struct ciss_cmd *cmd; 831 832 ccb = ciss_get_ccb(sc); 833 if (ccb == NULL) 834 return ENOMEM; 835 ccb->ccb_len = sizeof(*stat); 836 ccb->ccb_data = stat; 837 ccb->ccb_xs = NULL; 838 cmd = &ccb->ccb_cmd; 839 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 840 cmd->tgt2 = 0; 841 cmd->cdblen = 10; 842 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 843 cmd->tmo = htole16(0); 844 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 845 cmd->cdb[0] = CISS_CMD_CTRL_GET; 846 cmd->cdb[1] = target; 847 cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT; 848 cmd->cdb[7] = sizeof(*stat) >> 8; /* biiiig endian */ 849 cmd->cdb[8] = sizeof(*stat) & 0xff; 850 851 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag); 852 } 853 854 int 855 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait) 856 { 857 struct ciss_ccb *ccb; 858 struct ciss_cmd *cmd; 859 860 ccb = ciss_get_ccb(sc); 861 if (ccb == NULL) 862 return ENOMEM; 863 ccb->ccb_len = sizeof(*id); 864 ccb->ccb_data = id; 865 ccb->ccb_xs = NULL; 866 cmd = &ccb->ccb_cmd; 867 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 868 cmd->tgt2 = 0; 869 cmd->cdblen = 10; 870 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 871 cmd->tmo = htole16(0); 872 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 873 cmd->cdb[0] = CISS_CMD_CTRL_GET; 874 cmd->cdb[2] = drv; 875 cmd->cdb[6] = CISS_CMS_CTRL_PDID; 876 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 877 cmd->cdb[8] = sizeof(*id) & 0xff; 878 879 return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait); 880 } 881 882 883 struct ciss_ld * 884 ciss_pdscan(struct ciss_softc *sc, int ld) 885 { 886 struct ciss_pdid *pdid; 887 struct ciss_ld *ldp; 888 u_int8_t drv, buf[128]; 889 int i, j, k = 0; 890 891 mutex_enter(&sc->sc_mutex_scratch); 892 pdid = sc->scratch; 893 if (sc->ndrives == 256) { 894 for (i = 0; i < CISS_BIGBIT; i++) 895 if (!ciss_pdid(sc, i, pdid, 896 XS_CTL_POLL|XS_CTL_NOSLEEP) && 897 (pdid->present & CISS_PD_PRESENT)) 898 buf[k++] = i; 899 } else 900 for (i = 0; i < sc->nbus; i++) 901 for (j = 0; j < sc->ndrives; j++) { 902 drv = CISS_BIGBIT + i * sc->ndrives + j; 903 if (!ciss_pdid(sc, drv, pdid, 904 XS_CTL_POLL|XS_CTL_NOSLEEP)) 905 buf[k++] = drv; 906 } 907 mutex_exit(&sc->sc_mutex_scratch); 908 909 if (!k) 910 return NULL; 911 912 ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT); 913 if (!ldp) 914 return NULL; 915 916 bzero(&ldp->bling, sizeof(ldp->bling)); 917 ldp->ndrives = k; 918 ldp->xname[0] = 0; 919 bcopy(buf, ldp->tgts, k); 920 return ldp; 921 } 922 923 #if 0 924 static void 925 ciss_scsi_raw_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, 926 void *arg) /* TODO */ 927 { 928 struct scsipi_xfer *xs = (struct scsipi_xfer *) arg; 929 struct ciss_rawsoftc *rsc = 930 (struct ciss_rawsoftc *) chan->chan_adapter->adapt_dev; 931 struct ciss_softc *sc = rsc->sc_softc; 932 struct ciss_ccb *ccb; 933 struct ciss_cmd *cmd; 934 int error; 935 936 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd ")); 937 938 switch (req) 939 { 940 case ADAPTER_REQ_RUN_XFER: 941 if (xs->cmdlen > CISS_MAX_CDB) { 942 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 943 bzero(&xs->sense, sizeof(xs->sense)); 944 printf("ciss driver stuffup in %s:%d: %s()\n", 945 __FILE__, __LINE__, __func__); 946 xs->error = XS_DRIVER_STUFFUP; 947 scsipi_done(xs); 948 break; 949 } 950 951 error = 0; 952 xs->error = XS_NOERROR; 953 954 /* TODO check this target has not yet employed w/ any volume */ 955 956 ccb = ciss_get_ccb(sc); 957 cmd = &ccb->ccb_cmd; 958 ccb->ccb_len = xs->datalen; 959 ccb->ccb_data = xs->data; 960 ccb->ccb_xs = xs; 961 962 cmd->cdblen = xs->cmdlen; 963 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 964 if (xs->xs_control & XS_CTL_DATA_IN) 965 cmd->flags |= CISS_CDB_IN; 966 else if (xs->xs_control & XS_CTL_DATA_OUT) 967 cmd->flags |= CISS_CDB_OUT; 968 cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000; 969 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 970 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB); 971 972 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 973 xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) { 974 printf("ciss driver stuffup in %s:%d: %s()\n", 975 __FILE__, __LINE__, __func__); 976 xs->error = XS_DRIVER_STUFFUP; 977 scsipi_done(xs); 978 break; 979 } 980 981 break; 982 983 case ADAPTER_REQ_GROW_RESOURCES: 984 /* 985 * Not supported. 986 */ 987 break; 988 989 case ADAPTER_REQ_SET_XFER_MODE: 990 /* 991 * We can't change the transfer mode, but at least let 992 * scsipi know what the adapter has negociated. 993 */ 994 /* Get xfer mode and return it */ 995 break; 996 } 997 } 998 #endif 999 1000 static void 1001 ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1002 void *arg) 1003 { 1004 struct scsipi_xfer *xs = (struct scsipi_xfer *) arg; 1005 struct ciss_softc *sc = 1006 (struct ciss_softc *) chan->chan_adapter->adapt_dev; 1007 u_int8_t target; 1008 struct ciss_ccb *ccb; 1009 struct ciss_cmd *cmd; 1010 int error; 1011 1012 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd ")); 1013 1014 switch (req) 1015 { 1016 case ADAPTER_REQ_RUN_XFER: 1017 target = xs->xs_periph->periph_target; 1018 CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target)); 1019 if (xs->cmdlen > CISS_MAX_CDB) { 1020 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 1021 bzero(&xs->sense, sizeof(xs->sense)); 1022 printf("ciss driver stuffup in %s:%d: %s()\n", 1023 __FILE__, __LINE__, __func__); 1024 xs->error = XS_DRIVER_STUFFUP; 1025 scsipi_done(xs); 1026 break; 1027 } 1028 1029 error = 0; 1030 xs->error = XS_NOERROR; 1031 1032 /* XXX emulate SYNCHRONIZE_CACHE ??? */ 1033 1034 ccb = ciss_get_ccb(sc); 1035 cmd = &ccb->ccb_cmd; 1036 ccb->ccb_len = xs->datalen; 1037 ccb->ccb_data = xs->data; 1038 ccb->ccb_xs = xs; 1039 cmd->tgt = CISS_CMD_MODE_LD | target; 1040 cmd->tgt2 = 0; 1041 cmd->cdblen = xs->cmdlen; 1042 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 1043 if (xs->xs_control & XS_CTL_DATA_IN) 1044 cmd->flags |= CISS_CDB_IN; 1045 else if (xs->xs_control & XS_CTL_DATA_OUT) 1046 cmd->flags |= CISS_CDB_OUT; 1047 cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000; 1048 bzero(&cmd->cdb[0], sizeof(cmd->cdb)); 1049 bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB); 1050 CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ", 1051 cmd->cdb[0], cmd->cdb[1], cmd->cdb[2], 1052 cmd->cdb[3], cmd->cdb[4], cmd->cdb[5])); 1053 1054 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 1055 xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) { 1056 printf("ciss driver stuffup in %s:%d: %s()\n", 1057 __FILE__, __LINE__, __func__); 1058 xs->error = XS_DRIVER_STUFFUP; 1059 scsipi_done(xs); 1060 return; 1061 } 1062 1063 break; 1064 case ADAPTER_REQ_GROW_RESOURCES: 1065 /* 1066 * Not supported. 1067 */ 1068 break; 1069 case ADAPTER_REQ_SET_XFER_MODE: 1070 /* 1071 * We can't change the transfer mode, but at least let 1072 * scsipi know what the adapter has negociated. 1073 */ 1074 /* FIXME: get xfer mode and write it into arg */ 1075 break; 1076 } 1077 } 1078 1079 int 1080 ciss_intr(void *v) 1081 { 1082 struct ciss_softc *sc = v; 1083 struct ciss_ccb *ccb; 1084 u_int32_t id; 1085 int hit = 0; 1086 1087 CISS_DPRINTF(CISS_D_INTR, ("intr ")); 1088 1089 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem)) 1090 return 0; 1091 1092 while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) != 1093 0xffffffff) { 1094 1095 ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen); 1096 ccb->ccb_cmd.id = htole32(id); 1097 if (ccb->ccb_state == CISS_CCB_POLL) { 1098 ccb->ccb_state = CISS_CCB_ONQ; 1099 mutex_enter(&sc->sc_mutex); 1100 cv_broadcast(&sc->sc_condvar); 1101 mutex_exit(&sc->sc_mutex); 1102 } else 1103 ciss_done(ccb); 1104 1105 hit = 1; 1106 } 1107 1108 CISS_DPRINTF(CISS_D_INTR, ("exit\n")); 1109 return hit; 1110 } 1111 1112 static void 1113 ciss_heartbeat(void *v) 1114 { 1115 struct ciss_softc *sc = v; 1116 u_int32_t hb; 1117 1118 hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh, 1119 sc->cfgoff + offsetof(struct ciss_config, heartbeat)); 1120 if (hb == sc->heartbeat) 1121 panic("ciss: dead"); /* XX reset! */ 1122 else 1123 sc->heartbeat = hb; 1124 1125 callout_schedule(&sc->sc_hb, hz * 3); 1126 } 1127 1128 static int 1129 ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd, 1130 void *addr, int flag, struct proc *p) 1131 { 1132 #if NBIO > 0 1133 return ciss_ioctl(chan->chan_adapter->adapt_dev, cmd, addr); 1134 #else 1135 return ENOTTY; 1136 #endif 1137 } 1138 1139 #if NBIO > 0 1140 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 }; 1141 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 1142 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 1143 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 1144 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 1145 1146 int 1147 ciss_ioctl(struct device *dev, u_long cmd, void *addr) 1148 { 1149 struct ciss_softc *sc = (struct ciss_softc *)dev; 1150 struct bioc_inq *bi; 1151 struct bioc_disk *bd; 1152 struct bioc_blink *bb; 1153 struct ciss_ldstat *ldstat; 1154 struct ciss_pdid *pdid; 1155 struct ciss_blink *blink; 1156 struct ciss_ld *ldp; 1157 u_int8_t drv; 1158 int ld, pd, error = 0; 1159 1160 switch (cmd) { 1161 case BIOCINQ: 1162 bi = (struct bioc_inq *)addr; 1163 strlcpy(bi->bi_dev, device_xname(&sc->sc_dev), sizeof(bi->bi_dev)); 1164 bi->bi_novol = sc->maxunits; 1165 bi->bi_nodisk = sc->sc_lds[0]->ndrives; 1166 break; 1167 1168 case BIOCVOL: 1169 error = ciss_ioctl_vol(sc, (struct bioc_vol *)addr); 1170 break; 1171 1172 case BIOCDISK_NOVOL: 1173 /* 1174 * XXX since we don't know how to associate physical drives with logical drives 1175 * yet, BIOCDISK_NOVOL is equivalent to BIOCDISK to the volume that we've 1176 * associated all physical drives to. 1177 * Maybe assoicate all physical drives to all logical volumes, but only return 1178 * physical drives on one logical volume. Which one? Either 1st volume that 1179 * is degraded, rebuilding, or failed? 1180 */ 1181 bd = (struct bioc_disk *)addr; 1182 bd->bd_volid = 0; 1183 bd->bd_disknovol = true; 1184 /* FALLTHROUGH */ 1185 case BIOCDISK: 1186 bd = (struct bioc_disk *)addr; 1187 if (bd->bd_volid > sc->maxunits) { 1188 error = EINVAL; 1189 break; 1190 } 1191 ldp = sc->sc_lds[0]; 1192 if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) { 1193 error = EINVAL; 1194 break; 1195 } 1196 ldstat = sc->scratch; 1197 if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) { 1198 break; 1199 } 1200 bd->bd_status = -1; 1201 if (ldstat->stat == CISS_LD_REBLD && 1202 ldstat->bigrebuild == ldp->tgts[pd]) 1203 bd->bd_status = BIOC_SDREBUILD; 1204 if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT), 1205 ldstat->bigfailed)) { 1206 bd->bd_status = BIOC_SDFAILED; 1207 bd->bd_size = 0; 1208 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1209 sc->ndrives; 1210 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1211 bd->bd_lun = 0; 1212 bd->bd_vendor[0] = '\0'; 1213 bd->bd_serial[0] = '\0'; 1214 bd->bd_procdev[0] = '\0'; 1215 } else { 1216 pdid = sc->scratch; 1217 if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, 1218 XS_CTL_POLL))) { 1219 bd->bd_status = BIOC_SDFAILED; 1220 bd->bd_size = 0; 1221 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1222 sc->ndrives; 1223 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1224 bd->bd_lun = 0; 1225 bd->bd_vendor[0] = '\0'; 1226 bd->bd_serial[0] = '\0'; 1227 bd->bd_procdev[0] = '\0'; 1228 error = 0; 1229 break; 1230 } 1231 if (bd->bd_status < 0) { 1232 if (pdid->config & CISS_PD_SPARE) 1233 bd->bd_status = BIOC_SDHOTSPARE; 1234 else if (pdid->present & CISS_PD_PRESENT) 1235 bd->bd_status = BIOC_SDONLINE; 1236 else 1237 bd->bd_status = BIOC_SDINVALID; 1238 } 1239 bd->bd_size = (u_int64_t)le32toh(pdid->nblocks) * 1240 le16toh(pdid->blksz); 1241 bd->bd_channel = pdid->bus; 1242 bd->bd_target = pdid->target; 1243 bd->bd_lun = 0; 1244 strlcpy(bd->bd_vendor, pdid->model, 1245 sizeof(bd->bd_vendor)); 1246 strlcpy(bd->bd_serial, pdid->serial, 1247 sizeof(bd->bd_serial)); 1248 bd->bd_procdev[0] = '\0'; 1249 } 1250 break; 1251 1252 case BIOCBLINK: 1253 bb = (struct bioc_blink *)addr; 1254 blink = sc->scratch; 1255 error = EINVAL; 1256 /* XXX workaround completely dumb scsi addressing */ 1257 for (ld = 0; ld < sc->maxunits; ld++) { 1258 ldp = sc->sc_lds[ld]; 1259 if (!ldp) 1260 continue; 1261 if (sc->ndrives == 256) 1262 drv = bb->bb_target; 1263 else 1264 drv = CISS_BIGBIT + 1265 bb->bb_channel * sc->ndrives + 1266 bb->bb_target; 1267 for (pd = 0; pd < ldp->ndrives; pd++) 1268 if (ldp->tgts[pd] == drv) 1269 error = ciss_blink(sc, ld, pd, 1270 bb->bb_status, blink); 1271 } 1272 break; 1273 1274 case BIOCALARM: 1275 case BIOCSETSTATE: 1276 default: 1277 error = EINVAL; 1278 } 1279 1280 return (error); 1281 } 1282 1283 int 1284 ciss_ioctl_vol(struct ciss_softc *sc, struct bioc_vol *bv) 1285 { 1286 struct ciss_ldid *ldid; 1287 struct ciss_ld *ldp; 1288 struct ciss_ldstat *ldstat; 1289 struct ciss_pdid *pdid; 1290 int error = 0; 1291 u_int blks; 1292 1293 if (bv->bv_volid > sc->maxunits) { 1294 return EINVAL; 1295 } 1296 ldp = sc->sc_lds[bv->bv_volid]; 1297 ldid = sc->scratch; 1298 if ((error = ciss_ldid(sc, bv->bv_volid, ldid))) { 1299 return error; 1300 } 1301 bv->bv_status = BIOC_SVINVALID; 1302 blks = (u_int)le16toh(ldid->nblocks[1]) << 16 | 1303 le16toh(ldid->nblocks[0]); 1304 bv->bv_size = blks * (u_quad_t)le16toh(ldid->blksize); 1305 bv->bv_level = ciss_level[ldid->type]; 1306 /* 1307 * XXX Should only return bv_nodisk for logigal volume that we've associated 1308 * the physical drives to: either the 1st degraded, rebuilding, or failed 1309 * volume else volume 0? 1310 */ 1311 if (ldp) { 1312 bv->bv_nodisk = ldp->ndrives; 1313 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1314 } 1315 strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor)); 1316 ldstat = sc->scratch; 1317 bzero(ldstat, sizeof(*ldstat)); 1318 if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat))) { 1319 return error; 1320 } 1321 bv->bv_percent = -1; 1322 bv->bv_seconds = 0; 1323 if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0])) 1324 bv->bv_status = ciss_stat[ldstat->stat]; 1325 if (bv->bv_status == BIOC_SVREBUILD || 1326 bv->bv_status == BIOC_SVBUILDING) { 1327 u_int64_t prog; 1328 1329 ldp = sc->sc_lds[0]; 1330 if (ldp) { 1331 bv->bv_nodisk = ldp->ndrives; 1332 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1333 } 1334 /* 1335 * XXX ldstat->prog is blocks remaining on physical drive being rebuilt 1336 * blks is only correct for a RAID1 set; RAID5 needs to determine the 1337 * size of the physical device - which we don't yet know. 1338 * ldstat->bigrebuild has physical device target, so could be used with 1339 * pdid to get size. Another way is to save pd information in sc so it's 1340 * easy to reference. 1341 */ 1342 prog = (u_int64_t)((ldstat->prog[3] << 24) | 1343 (ldstat->prog[2] << 16) | (ldstat->prog[1] << 8) | 1344 ldstat->prog[0]); 1345 pdid = sc->scratch; 1346 if (!ciss_pdid(sc, ldstat->bigrebuild, pdid, XS_CTL_POLL)) { 1347 blks = le32toh(pdid->nblocks); 1348 bv->bv_percent = (blks - prog) * 1000ULL / blks; 1349 } 1350 } 1351 return 0; 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, XS_CTL_POLL); 1392 } 1393 1394 int 1395 ciss_create_sensors(struct ciss_softc *sc) 1396 { 1397 int i; 1398 int nsensors = sc->maxunits; 1399 1400 sc->sc_sme = sysmon_envsys_create(); 1401 sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors, 1402 M_DEVBUF, M_NOWAIT | M_ZERO); 1403 if (sc->sc_sensor == NULL) { 1404 aprint_error_dev(&sc->sc_dev, "can't allocate envsys_data"); 1405 return(ENOMEM); 1406 } 1407 1408 for (i = 0; i < nsensors; i++) { 1409 sc->sc_sensor[i].units = ENVSYS_DRIVE; 1410 sc->sc_sensor[i].monitor = true; 1411 /* Enable monitoring for drive state changes */ 1412 sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED; 1413 /* logical drives */ 1414 snprintf(sc->sc_sensor[i].desc, 1415 sizeof(sc->sc_sensor[i].desc), "%s:%d", 1416 device_xname(&sc->sc_dev), i); 1417 if (sysmon_envsys_sensor_attach(sc->sc_sme, 1418 &sc->sc_sensor[i])) 1419 goto out; 1420 } 1421 1422 sc->sc_sme->sme_name = device_xname(&sc->sc_dev); 1423 sc->sc_sme->sme_cookie = sc; 1424 sc->sc_sme->sme_refresh = ciss_sensor_refresh; 1425 if (sysmon_envsys_register(sc->sc_sme)) { 1426 printf("%s: unable to register with sysmon\n", device_xname(&sc->sc_dev)); 1427 return(1); 1428 } 1429 return (0); 1430 1431 out: 1432 free(sc->sc_sensor, M_DEVBUF); 1433 sysmon_envsys_destroy(sc->sc_sme); 1434 return EINVAL; 1435 } 1436 1437 void 1438 ciss_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 1439 { 1440 struct ciss_softc *sc = sme->sme_cookie; 1441 struct bioc_vol bv; 1442 1443 if (edata->sensor >= sc->maxunits) 1444 return; 1445 1446 bzero(&bv, sizeof(bv)); 1447 bv.bv_volid = edata->sensor; 1448 if (ciss_ioctl_vol(sc, &bv)) { 1449 return; 1450 } 1451 1452 switch(bv.bv_status) { 1453 case BIOC_SVOFFLINE: 1454 edata->value_cur = ENVSYS_DRIVE_FAIL; 1455 edata->state = ENVSYS_SCRITICAL; 1456 break; 1457 1458 case BIOC_SVDEGRADED: 1459 edata->value_cur = ENVSYS_DRIVE_PFAIL; 1460 edata->state = ENVSYS_SCRITICAL; 1461 break; 1462 1463 case BIOC_SVSCRUB: 1464 case BIOC_SVONLINE: 1465 edata->value_cur = ENVSYS_DRIVE_ONLINE; 1466 edata->state = ENVSYS_SVALID; 1467 break; 1468 1469 case BIOC_SVREBUILD: 1470 case BIOC_SVBUILDING: 1471 edata->value_cur = ENVSYS_DRIVE_REBUILD; 1472 edata->state = ENVSYS_SVALID; 1473 break; 1474 1475 case BIOC_SVINVALID: 1476 /* FALLTRHOUGH */ 1477 default: 1478 edata->value_cur = 0; /* unknown */ 1479 edata->state = ENVSYS_SINVALID; 1480 } 1481 } 1482 #endif /* NBIO > 0 */ 1483