1 /* $NetBSD: ciss.c,v 1.19 2009/05/12 14:25:17 cegger 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.19 2009/05/12 14:25:17 cegger 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(device_t, 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 memset(sc->ccbs, 0, 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 memset(sc->scratch, 0, 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 memset(sc->sc_lds, 0, 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 = (device_t) 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, 474 (u_long)sgd->ds_len)); 475 476 for (i = 0; i < dmap->dm_nsegs; sgd++, i++) { 477 cmd->sgl[i].addr_lo = htole32(sgd->ds_addr); 478 cmd->sgl[i].addr_hi = 479 htole32((u_int64_t)sgd->ds_addr >> 32); 480 cmd->sgl[i].len = htole32(sgd->ds_len); 481 cmd->sgl[i].flags = htole32(0); 482 if (i) { 483 CISS_DPRINTF(CISS_D_DMA, 484 (",0x%lx/%lu", sgd->ds_addr, 485 (u_long)sgd->ds_len)); 486 } 487 } 488 489 CISS_DPRINTF(CISS_D_DMA, ("> ")); 490 491 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 492 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 493 } else 494 cmd->sgin = 0; 495 cmd->sglen = htole16((u_int16_t)cmd->sgin); 496 memset(&ccb->ccb_err, 0, sizeof(ccb->ccb_err)); 497 498 bus_dmamap_sync(sc->sc_dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize, 499 BUS_DMASYNC_PREWRITE); 500 501 if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP)) 502 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR, 503 bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) | sc->iem); 504 505 mutex_enter(&sc->sc_mutex); 506 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link); 507 mutex_exit(&sc->sc_mutex); 508 ccb->ccb_state = CISS_CCB_ONQ; 509 CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); 510 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa); 511 512 if (wait & XS_CTL_POLL) { 513 int etick; 514 CISS_DPRINTF(CISS_D_CMD, ("waiting ")); 515 516 i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000; 517 tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000); 518 if (tohz == 0) 519 tohz = 1; 520 for (i *= 100, etick = tick + tohz; i--; ) { 521 if (!(wait & XS_CTL_NOSLEEP)) { 522 ccb->ccb_state = CISS_CCB_POLL; 523 CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz)); 524 mutex_enter(&sc->sc_mutex); 525 if (cv_timedwait(&sc->sc_condvar, 526 &sc->sc_mutex, tohz) == EWOULDBLOCK) { 527 mutex_exit(&sc->sc_mutex); 528 break; 529 } 530 mutex_exit(&sc->sc_mutex); 531 if (ccb->ccb_state != CISS_CCB_ONQ) { 532 tohz = etick - tick; 533 if (tohz <= 0) 534 break; 535 CISS_DPRINTF(CISS_D_CMD, ("T")); 536 continue; 537 } 538 ccb1 = ccb; 539 } else { 540 DELAY(10); 541 542 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, 543 CISS_ISR) & sc->iem)) { 544 CISS_DPRINTF(CISS_D_CMD, ("N")); 545 continue; 546 } 547 548 if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 549 CISS_OUTQ)) == 0xffffffff) { 550 CISS_DPRINTF(CISS_D_CMD, ("Q")); 551 continue; 552 } 553 554 CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); 555 ccb1 = (struct ciss_ccb *) 556 ((char *)sc->ccbs + (id >> 2) * sc->ccblen); 557 ccb1->ccb_cmd.id = htole32(id); 558 } 559 560 error = ciss_done(ccb1); 561 if (ccb1 == ccb) 562 break; 563 } 564 565 /* if never got a chance to be done above... */ 566 if (ccb->ccb_state != CISS_CCB_FREE) { 567 ccb->ccb_err.cmd_stat = CISS_ERR_TMO; 568 error = ciss_done(ccb); 569 } 570 571 CISS_DPRINTF(CISS_D_CMD, ("done %d:%d", 572 ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat)); 573 } 574 575 if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP)) 576 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR, 577 bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) & ~sc->iem); 578 579 return (error); 580 } 581 582 static int 583 ciss_done(struct ciss_ccb *ccb) 584 { 585 struct ciss_softc *sc = ccb->ccb_sc; 586 struct scsipi_xfer *xs = ccb->ccb_xs; 587 struct ciss_cmd *cmd; 588 int error = 0; 589 590 CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb)); 591 592 if (ccb->ccb_state != CISS_CCB_ONQ) { 593 printf("%s: unqueued ccb %p ready, state=0x%x\n", 594 device_xname(&sc->sc_dev), ccb, ccb->ccb_state); 595 return 1; 596 } 597 598 ccb->ccb_state = CISS_CCB_READY; 599 mutex_enter(&sc->sc_mutex); 600 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link); 601 mutex_exit(&sc->sc_mutex); 602 603 if (ccb->ccb_cmd.id & CISS_CMD_ERR) 604 error = ciss_error(ccb); 605 606 cmd = &ccb->ccb_cmd; 607 if (ccb->ccb_data) { 608 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 609 ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ? 610 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 611 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); 612 ccb->ccb_xs = NULL; 613 ccb->ccb_data = NULL; 614 } 615 616 ciss_put_ccb(ccb); 617 618 if (xs) { 619 xs->resid = 0; 620 CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs)); 621 scsipi_done(xs); 622 } 623 624 return error; 625 } 626 627 static int 628 ciss_error(struct ciss_ccb *ccb) 629 { 630 struct ciss_softc *sc = ccb->ccb_sc; 631 struct ciss_error *err = &ccb->ccb_err; 632 struct scsipi_xfer *xs = ccb->ccb_xs; 633 int rv; 634 635 switch ((rv = le16toh(err->cmd_stat))) { 636 case CISS_ERR_OK: 637 break; 638 639 case CISS_ERR_INVCMD: 640 printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n", 641 device_xname(&sc->sc_dev), ccb->ccb_cmd.id, 642 err->err_info, err->err_type[3], err->err_type[2]); 643 if (xs) { 644 memset(&xs->sense, 0, sizeof(xs->sense)); 645 xs->sense.scsi_sense.response_code = 646 SSD_RCODE_CURRENT | SSD_RCODE_VALID; 647 xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST; 648 xs->sense.scsi_sense.asc = 0x24; /* ill field */ 649 xs->sense.scsi_sense.ascq = 0x0; 650 xs->error = XS_SENSE; 651 } 652 break; 653 654 case CISS_ERR_TMO: 655 xs->error = XS_TIMEOUT; 656 break; 657 658 case CISS_ERR_UNRUN: 659 /* Underrun */ 660 xs->resid = le32toh(err->resid); 661 CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ", 662 xs->resid)); 663 break; 664 default: 665 if (xs) { 666 CISS_DPRINTF(CISS_D_CMD, ("scsi_stat=%x ", err->scsi_stat)); 667 switch (err->scsi_stat) { 668 case SCSI_CHECK: 669 xs->error = XS_SENSE; 670 memcpy(&xs->sense, &err->sense[0], 671 sizeof(xs->sense)); 672 CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ", 673 err->sense[0], err->sense[1], err->sense[2], err->sense[3])); 674 break; 675 676 case XS_BUSY: 677 xs->error = XS_BUSY; 678 break; 679 680 default: 681 CISS_DPRINTF(CISS_D_ERR, ("%s: " 682 "cmd_stat=%x scsi_stat=0x%x resid=0x%x\n", 683 device_xname(&sc->sc_dev), rv, err->scsi_stat, 684 le32toh(err->resid))); 685 printf("ciss driver stuffup in %s:%d: %s()\n", 686 __FILE__, __LINE__, __func__); 687 xs->error = XS_DRIVER_STUFFUP; 688 break; 689 } 690 xs->resid = le32toh(err->resid); 691 } 692 } 693 ccb->ccb_cmd.id &= htole32(~3); 694 695 return rv; 696 } 697 698 static int 699 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq) 700 { 701 struct ciss_ccb *ccb; 702 struct ciss_cmd *cmd; 703 704 ccb = ciss_get_ccb(sc); 705 ccb->ccb_len = sizeof(*inq); 706 ccb->ccb_data = inq; 707 ccb->ccb_xs = NULL; 708 cmd = &ccb->ccb_cmd; 709 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 710 cmd->tgt2 = 0; 711 cmd->cdblen = 10; 712 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 713 cmd->tmo = htole16(0); 714 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 715 cmd->cdb[0] = CISS_CMD_CTRL_GET; 716 cmd->cdb[6] = CISS_CMS_CTRL_CTRL; 717 cmd->cdb[7] = sizeof(*inq) >> 8; /* biiiig endian */ 718 cmd->cdb[8] = sizeof(*inq) & 0xff; 719 720 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 721 } 722 723 static int 724 ciss_ldmap(struct ciss_softc *sc) 725 { 726 struct ciss_ccb *ccb; 727 struct ciss_cmd *cmd; 728 struct ciss_ldmap *lmap; 729 int total, rv; 730 731 mutex_enter(&sc->sc_mutex_scratch); 732 lmap = sc->scratch; 733 lmap->size = htobe32(sc->maxunits * sizeof(lmap->map)); 734 total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map); 735 736 ccb = ciss_get_ccb(sc); 737 ccb->ccb_len = total; 738 ccb->ccb_data = lmap; 739 ccb->ccb_xs = NULL; 740 cmd = &ccb->ccb_cmd; 741 cmd->tgt = CISS_CMD_MODE_PERIPH; 742 cmd->tgt2 = 0; 743 cmd->cdblen = 12; 744 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 745 cmd->tmo = htole16(30); 746 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 747 cmd->cdb[0] = CISS_CMD_LDMAP; 748 cmd->cdb[8] = total >> 8; /* biiiig endian */ 749 cmd->cdb[9] = total & 0xff; 750 751 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 752 753 if (rv) { 754 mutex_exit(&sc->sc_mutex_scratch); 755 return rv; 756 } 757 758 CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n", 759 lmap->map[0].tgt, lmap->map[0].tgt2)); 760 761 mutex_exit(&sc->sc_mutex_scratch); 762 return 0; 763 } 764 765 static int 766 ciss_sync(struct ciss_softc *sc) 767 { 768 struct ciss_ccb *ccb; 769 struct ciss_cmd *cmd; 770 struct ciss_flush *flush; 771 int rv; 772 773 mutex_enter(&sc->sc_mutex_scratch); 774 flush = sc->scratch; 775 memset(flush, 0, sizeof(*flush)); 776 flush->flush = sc->sc_flush; 777 778 ccb = ciss_get_ccb(sc); 779 ccb->ccb_len = sizeof(*flush); 780 ccb->ccb_data = flush; 781 ccb->ccb_xs = NULL; 782 cmd = &ccb->ccb_cmd; 783 cmd->tgt = CISS_CMD_MODE_PERIPH; 784 cmd->tgt2 = 0; 785 cmd->cdblen = 10; 786 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 787 cmd->tmo = 0; 788 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 789 cmd->cdb[0] = CISS_CMD_CTRL_SET; 790 cmd->cdb[6] = CISS_CMS_CTRL_FLUSH; 791 cmd->cdb[7] = sizeof(*flush) >> 8; /* biiiig endian */ 792 cmd->cdb[8] = sizeof(*flush) & 0xff; 793 794 rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP); 795 mutex_exit(&sc->sc_mutex_scratch); 796 797 return rv; 798 } 799 800 int 801 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id) 802 { 803 struct ciss_ccb *ccb; 804 struct ciss_cmd *cmd; 805 806 ccb = ciss_get_ccb(sc); 807 if (ccb == NULL) 808 return ENOMEM; 809 ccb->ccb_len = sizeof(*id); 810 ccb->ccb_data = id; 811 ccb->ccb_xs = NULL; 812 cmd = &ccb->ccb_cmd; 813 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 814 cmd->tgt2 = 0; 815 cmd->cdblen = 10; 816 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 817 cmd->tmo = htole16(0); 818 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 819 cmd->cdb[0] = CISS_CMD_CTRL_GET; 820 cmd->cdb[1] = target; 821 cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT; 822 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 823 cmd->cdb[8] = sizeof(*id) & 0xff; 824 825 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag); 826 } 827 828 int 829 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat) 830 { 831 struct ciss_ccb *ccb; 832 struct ciss_cmd *cmd; 833 834 ccb = ciss_get_ccb(sc); 835 if (ccb == NULL) 836 return ENOMEM; 837 ccb->ccb_len = sizeof(*stat); 838 ccb->ccb_data = stat; 839 ccb->ccb_xs = NULL; 840 cmd = &ccb->ccb_cmd; 841 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 842 cmd->tgt2 = 0; 843 cmd->cdblen = 10; 844 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 845 cmd->tmo = htole16(0); 846 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 847 cmd->cdb[0] = CISS_CMD_CTRL_GET; 848 cmd->cdb[1] = target; 849 cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT; 850 cmd->cdb[7] = sizeof(*stat) >> 8; /* biiiig endian */ 851 cmd->cdb[8] = sizeof(*stat) & 0xff; 852 853 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag); 854 } 855 856 int 857 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait) 858 { 859 struct ciss_ccb *ccb; 860 struct ciss_cmd *cmd; 861 862 ccb = ciss_get_ccb(sc); 863 if (ccb == NULL) 864 return ENOMEM; 865 ccb->ccb_len = sizeof(*id); 866 ccb->ccb_data = id; 867 ccb->ccb_xs = NULL; 868 cmd = &ccb->ccb_cmd; 869 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 870 cmd->tgt2 = 0; 871 cmd->cdblen = 10; 872 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN; 873 cmd->tmo = htole16(0); 874 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 875 cmd->cdb[0] = CISS_CMD_CTRL_GET; 876 cmd->cdb[2] = drv; 877 cmd->cdb[6] = CISS_CMS_CTRL_PDID; 878 cmd->cdb[7] = sizeof(*id) >> 8; /* biiiig endian */ 879 cmd->cdb[8] = sizeof(*id) & 0xff; 880 881 return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait); 882 } 883 884 885 struct ciss_ld * 886 ciss_pdscan(struct ciss_softc *sc, int ld) 887 { 888 struct ciss_pdid *pdid; 889 struct ciss_ld *ldp; 890 u_int8_t drv, buf[128]; 891 int i, j, k = 0; 892 893 mutex_enter(&sc->sc_mutex_scratch); 894 pdid = sc->scratch; 895 if (sc->ndrives == 256) { 896 for (i = 0; i < CISS_BIGBIT; i++) 897 if (!ciss_pdid(sc, i, pdid, 898 XS_CTL_POLL|XS_CTL_NOSLEEP) && 899 (pdid->present & CISS_PD_PRESENT)) 900 buf[k++] = i; 901 } else 902 for (i = 0; i < sc->nbus; i++) 903 for (j = 0; j < sc->ndrives; j++) { 904 drv = CISS_BIGBIT + i * sc->ndrives + j; 905 if (!ciss_pdid(sc, drv, pdid, 906 XS_CTL_POLL|XS_CTL_NOSLEEP)) 907 buf[k++] = drv; 908 } 909 mutex_exit(&sc->sc_mutex_scratch); 910 911 if (!k) 912 return NULL; 913 914 ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT); 915 if (!ldp) 916 return NULL; 917 918 memset(&ldp->bling, 0, sizeof(ldp->bling)); 919 ldp->ndrives = k; 920 ldp->xname[0] = 0; 921 memcpy(ldp->tgts, buf, k); 922 return ldp; 923 } 924 925 #if 0 926 static void 927 ciss_scsi_raw_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, 928 void *arg) /* TODO */ 929 { 930 struct scsipi_xfer *xs = (struct scsipi_xfer *) arg; 931 struct ciss_rawsoftc *rsc = 932 (struct ciss_rawsoftc *) chan->chan_adapter->adapt_dev; 933 struct ciss_softc *sc = rsc->sc_softc; 934 struct ciss_ccb *ccb; 935 struct ciss_cmd *cmd; 936 int error; 937 938 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd ")); 939 940 switch (req) 941 { 942 case ADAPTER_REQ_RUN_XFER: 943 if (xs->cmdlen > CISS_MAX_CDB) { 944 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 945 memset(&xs->sense, 0, sizeof(xs->sense)); 946 printf("ciss driver stuffup in %s:%d: %s()\n", 947 __FILE__, __LINE__, __func__); 948 xs->error = XS_DRIVER_STUFFUP; 949 scsipi_done(xs); 950 break; 951 } 952 953 error = 0; 954 xs->error = XS_NOERROR; 955 956 /* TODO check this target has not yet employed w/ any volume */ 957 958 ccb = ciss_get_ccb(sc); 959 cmd = &ccb->ccb_cmd; 960 ccb->ccb_len = xs->datalen; 961 ccb->ccb_data = xs->data; 962 ccb->ccb_xs = xs; 963 964 cmd->cdblen = xs->cmdlen; 965 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 966 if (xs->xs_control & XS_CTL_DATA_IN) 967 cmd->flags |= CISS_CDB_IN; 968 else if (xs->xs_control & XS_CTL_DATA_OUT) 969 cmd->flags |= CISS_CDB_OUT; 970 cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000; 971 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 972 memcpy(&cmd->cdb[0], xs->cmd, CISS_MAX_CDB); 973 974 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 975 xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) { 976 printf("ciss driver stuffup in %s:%d: %s()\n", 977 __FILE__, __LINE__, __func__); 978 xs->error = XS_DRIVER_STUFFUP; 979 scsipi_done(xs); 980 break; 981 } 982 983 break; 984 985 case ADAPTER_REQ_GROW_RESOURCES: 986 /* 987 * Not supported. 988 */ 989 break; 990 991 case ADAPTER_REQ_SET_XFER_MODE: 992 /* 993 * We can't change the transfer mode, but at least let 994 * scsipi know what the adapter has negociated. 995 */ 996 /* Get xfer mode and return it */ 997 break; 998 } 999 } 1000 #endif 1001 1002 static void 1003 ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1004 void *arg) 1005 { 1006 struct scsipi_xfer *xs = (struct scsipi_xfer *) arg; 1007 struct ciss_softc *sc = 1008 (struct ciss_softc *) chan->chan_adapter->adapt_dev; 1009 u_int8_t target; 1010 struct ciss_ccb *ccb; 1011 struct ciss_cmd *cmd; 1012 int error; 1013 1014 CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd ")); 1015 1016 switch (req) 1017 { 1018 case ADAPTER_REQ_RUN_XFER: 1019 target = xs->xs_periph->periph_target; 1020 CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target)); 1021 if (xs->cmdlen > CISS_MAX_CDB) { 1022 CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); 1023 memset(&xs->sense, 0, sizeof(xs->sense)); 1024 printf("ciss driver stuffup in %s:%d: %s()\n", 1025 __FILE__, __LINE__, __func__); 1026 xs->error = XS_DRIVER_STUFFUP; 1027 scsipi_done(xs); 1028 break; 1029 } 1030 1031 error = 0; 1032 xs->error = XS_NOERROR; 1033 1034 /* XXX emulate SYNCHRONIZE_CACHE ??? */ 1035 1036 ccb = ciss_get_ccb(sc); 1037 cmd = &ccb->ccb_cmd; 1038 ccb->ccb_len = xs->datalen; 1039 ccb->ccb_data = xs->data; 1040 ccb->ccb_xs = xs; 1041 cmd->tgt = CISS_CMD_MODE_LD | target; 1042 cmd->tgt2 = 0; 1043 cmd->cdblen = xs->cmdlen; 1044 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL; 1045 if (xs->xs_control & XS_CTL_DATA_IN) 1046 cmd->flags |= CISS_CDB_IN; 1047 else if (xs->xs_control & XS_CTL_DATA_OUT) 1048 cmd->flags |= CISS_CDB_OUT; 1049 cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000; 1050 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 1051 memcpy(&cmd->cdb[0], xs->cmd, CISS_MAX_CDB); 1052 CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ", 1053 cmd->cdb[0], cmd->cdb[1], cmd->cdb[2], 1054 cmd->cdb[3], cmd->cdb[4], cmd->cdb[5])); 1055 1056 if (ciss_cmd(ccb, BUS_DMA_WAITOK, 1057 xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) { 1058 printf("ciss driver stuffup in %s:%d: %s()\n", 1059 __FILE__, __LINE__, __func__); 1060 xs->error = XS_DRIVER_STUFFUP; 1061 scsipi_done(xs); 1062 return; 1063 } 1064 1065 break; 1066 case ADAPTER_REQ_GROW_RESOURCES: 1067 /* 1068 * Not supported. 1069 */ 1070 break; 1071 case ADAPTER_REQ_SET_XFER_MODE: 1072 /* 1073 * We can't change the transfer mode, but at least let 1074 * scsipi know what the adapter has negociated. 1075 */ 1076 /* FIXME: get xfer mode and write it into arg */ 1077 break; 1078 } 1079 } 1080 1081 int 1082 ciss_intr(void *v) 1083 { 1084 struct ciss_softc *sc = v; 1085 struct ciss_ccb *ccb; 1086 u_int32_t id; 1087 int hit = 0; 1088 1089 CISS_DPRINTF(CISS_D_INTR, ("intr ")); 1090 1091 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem)) 1092 return 0; 1093 1094 while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) != 1095 0xffffffff) { 1096 1097 ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen); 1098 ccb->ccb_cmd.id = htole32(id); 1099 if (ccb->ccb_state == CISS_CCB_POLL) { 1100 ccb->ccb_state = CISS_CCB_ONQ; 1101 mutex_enter(&sc->sc_mutex); 1102 cv_broadcast(&sc->sc_condvar); 1103 mutex_exit(&sc->sc_mutex); 1104 } else 1105 ciss_done(ccb); 1106 1107 hit = 1; 1108 } 1109 1110 CISS_DPRINTF(CISS_D_INTR, ("exit\n")); 1111 return hit; 1112 } 1113 1114 static void 1115 ciss_heartbeat(void *v) 1116 { 1117 struct ciss_softc *sc = v; 1118 u_int32_t hb; 1119 1120 hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh, 1121 sc->cfgoff + offsetof(struct ciss_config, heartbeat)); 1122 if (hb == sc->heartbeat) 1123 panic("ciss: dead"); /* XX reset! */ 1124 else 1125 sc->heartbeat = hb; 1126 1127 callout_schedule(&sc->sc_hb, hz * 3); 1128 } 1129 1130 static int 1131 ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd, 1132 void *addr, int flag, struct proc *p) 1133 { 1134 #if NBIO > 0 1135 return ciss_ioctl(chan->chan_adapter->adapt_dev, cmd, addr); 1136 #else 1137 return ENOTTY; 1138 #endif 1139 } 1140 1141 #if NBIO > 0 1142 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 }; 1143 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 1144 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 1145 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 1146 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 1147 1148 int 1149 ciss_ioctl(device_t dev, u_long cmd, void *addr) 1150 { 1151 struct ciss_softc *sc = (struct ciss_softc *)dev; 1152 struct bioc_inq *bi; 1153 struct bioc_disk *bd; 1154 struct bioc_blink *bb; 1155 struct ciss_ldstat *ldstat; 1156 struct ciss_pdid *pdid; 1157 struct ciss_blink *blink; 1158 struct ciss_ld *ldp; 1159 u_int8_t drv; 1160 int ld, pd, error = 0; 1161 1162 switch (cmd) { 1163 case BIOCINQ: 1164 bi = (struct bioc_inq *)addr; 1165 strlcpy(bi->bi_dev, device_xname(&sc->sc_dev), sizeof(bi->bi_dev)); 1166 bi->bi_novol = sc->maxunits; 1167 bi->bi_nodisk = sc->sc_lds[0]->ndrives; 1168 break; 1169 1170 case BIOCVOL: 1171 error = ciss_ioctl_vol(sc, (struct bioc_vol *)addr); 1172 break; 1173 1174 case BIOCDISK_NOVOL: 1175 /* 1176 * XXX since we don't know how to associate physical drives with logical drives 1177 * yet, BIOCDISK_NOVOL is equivalent to BIOCDISK to the volume that we've 1178 * associated all physical drives to. 1179 * Maybe assoicate all physical drives to all logical volumes, but only return 1180 * physical drives on one logical volume. Which one? Either 1st volume that 1181 * is degraded, rebuilding, or failed? 1182 */ 1183 bd = (struct bioc_disk *)addr; 1184 bd->bd_volid = 0; 1185 bd->bd_disknovol = true; 1186 /* FALLTHROUGH */ 1187 case BIOCDISK: 1188 bd = (struct bioc_disk *)addr; 1189 if (bd->bd_volid > sc->maxunits) { 1190 error = EINVAL; 1191 break; 1192 } 1193 ldp = sc->sc_lds[0]; 1194 if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) { 1195 error = EINVAL; 1196 break; 1197 } 1198 ldstat = sc->scratch; 1199 if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) { 1200 break; 1201 } 1202 bd->bd_status = -1; 1203 if (ldstat->stat == CISS_LD_REBLD && 1204 ldstat->bigrebuild == ldp->tgts[pd]) 1205 bd->bd_status = BIOC_SDREBUILD; 1206 if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT), 1207 ldstat->bigfailed)) { 1208 bd->bd_status = BIOC_SDFAILED; 1209 bd->bd_size = 0; 1210 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1211 sc->ndrives; 1212 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1213 bd->bd_lun = 0; 1214 bd->bd_vendor[0] = '\0'; 1215 bd->bd_serial[0] = '\0'; 1216 bd->bd_procdev[0] = '\0'; 1217 } else { 1218 pdid = sc->scratch; 1219 if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, 1220 XS_CTL_POLL))) { 1221 bd->bd_status = BIOC_SDFAILED; 1222 bd->bd_size = 0; 1223 bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) / 1224 sc->ndrives; 1225 bd->bd_target = ldp->tgts[pd] % sc->ndrives; 1226 bd->bd_lun = 0; 1227 bd->bd_vendor[0] = '\0'; 1228 bd->bd_serial[0] = '\0'; 1229 bd->bd_procdev[0] = '\0'; 1230 error = 0; 1231 break; 1232 } 1233 if (bd->bd_status < 0) { 1234 if (pdid->config & CISS_PD_SPARE) 1235 bd->bd_status = BIOC_SDHOTSPARE; 1236 else if (pdid->present & CISS_PD_PRESENT) 1237 bd->bd_status = BIOC_SDONLINE; 1238 else 1239 bd->bd_status = BIOC_SDINVALID; 1240 } 1241 bd->bd_size = (u_int64_t)le32toh(pdid->nblocks) * 1242 le16toh(pdid->blksz); 1243 bd->bd_channel = pdid->bus; 1244 bd->bd_target = pdid->target; 1245 bd->bd_lun = 0; 1246 strlcpy(bd->bd_vendor, pdid->model, 1247 sizeof(bd->bd_vendor)); 1248 strlcpy(bd->bd_serial, pdid->serial, 1249 sizeof(bd->bd_serial)); 1250 bd->bd_procdev[0] = '\0'; 1251 } 1252 break; 1253 1254 case BIOCBLINK: 1255 bb = (struct bioc_blink *)addr; 1256 blink = sc->scratch; 1257 error = EINVAL; 1258 /* XXX workaround completely dumb scsi addressing */ 1259 for (ld = 0; ld < sc->maxunits; ld++) { 1260 ldp = sc->sc_lds[ld]; 1261 if (!ldp) 1262 continue; 1263 if (sc->ndrives == 256) 1264 drv = bb->bb_target; 1265 else 1266 drv = CISS_BIGBIT + 1267 bb->bb_channel * sc->ndrives + 1268 bb->bb_target; 1269 for (pd = 0; pd < ldp->ndrives; pd++) 1270 if (ldp->tgts[pd] == drv) 1271 error = ciss_blink(sc, ld, pd, 1272 bb->bb_status, blink); 1273 } 1274 break; 1275 1276 case BIOCALARM: 1277 case BIOCSETSTATE: 1278 default: 1279 error = EINVAL; 1280 } 1281 1282 return (error); 1283 } 1284 1285 int 1286 ciss_ioctl_vol(struct ciss_softc *sc, struct bioc_vol *bv) 1287 { 1288 struct ciss_ldid *ldid; 1289 struct ciss_ld *ldp; 1290 struct ciss_ldstat *ldstat; 1291 struct ciss_pdid *pdid; 1292 int error = 0; 1293 u_int blks; 1294 1295 if (bv->bv_volid > sc->maxunits) { 1296 return EINVAL; 1297 } 1298 ldp = sc->sc_lds[bv->bv_volid]; 1299 ldid = sc->scratch; 1300 if ((error = ciss_ldid(sc, bv->bv_volid, ldid))) { 1301 return error; 1302 } 1303 bv->bv_status = BIOC_SVINVALID; 1304 blks = (u_int)le16toh(ldid->nblocks[1]) << 16 | 1305 le16toh(ldid->nblocks[0]); 1306 bv->bv_size = blks * (u_quad_t)le16toh(ldid->blksize); 1307 bv->bv_level = ciss_level[ldid->type]; 1308 /* 1309 * XXX Should only return bv_nodisk for logigal volume that we've associated 1310 * the physical drives to: either the 1st degraded, rebuilding, or failed 1311 * volume else volume 0? 1312 */ 1313 if (ldp) { 1314 bv->bv_nodisk = ldp->ndrives; 1315 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1316 } 1317 strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor)); 1318 ldstat = sc->scratch; 1319 memset(ldstat, 0, sizeof(*ldstat)); 1320 if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat))) { 1321 return error; 1322 } 1323 bv->bv_percent = -1; 1324 bv->bv_seconds = 0; 1325 if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0])) 1326 bv->bv_status = ciss_stat[ldstat->stat]; 1327 if (bv->bv_status == BIOC_SVREBUILD || 1328 bv->bv_status == BIOC_SVBUILDING) { 1329 u_int64_t prog; 1330 1331 ldp = sc->sc_lds[0]; 1332 if (ldp) { 1333 bv->bv_nodisk = ldp->ndrives; 1334 strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev)); 1335 } 1336 /* 1337 * XXX ldstat->prog is blocks remaining on physical drive being rebuilt 1338 * blks is only correct for a RAID1 set; RAID5 needs to determine the 1339 * size of the physical device - which we don't yet know. 1340 * ldstat->bigrebuild has physical device target, so could be used with 1341 * pdid to get size. Another way is to save pd information in sc so it's 1342 * easy to reference. 1343 */ 1344 prog = (u_int64_t)((ldstat->prog[3] << 24) | 1345 (ldstat->prog[2] << 16) | (ldstat->prog[1] << 8) | 1346 ldstat->prog[0]); 1347 pdid = sc->scratch; 1348 if (!ciss_pdid(sc, ldstat->bigrebuild, pdid, XS_CTL_POLL)) { 1349 blks = le32toh(pdid->nblocks); 1350 bv->bv_percent = (blks - prog) * 1000ULL / blks; 1351 } 1352 } 1353 return 0; 1354 } 1355 1356 int 1357 ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat, 1358 struct ciss_blink *blink) 1359 { 1360 struct ciss_ccb *ccb; 1361 struct ciss_cmd *cmd; 1362 struct ciss_ld *ldp; 1363 1364 if (ld > sc->maxunits) 1365 return EINVAL; 1366 1367 ldp = sc->sc_lds[ld]; 1368 if (!ldp || pd > ldp->ndrives) 1369 return EINVAL; 1370 1371 ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 : 1372 CISS_BLINK_ALL; 1373 memcpy(blink, &ldp->bling, sizeof(*blink)); 1374 1375 ccb = ciss_get_ccb(sc); 1376 if (ccb == NULL) 1377 return ENOMEM; 1378 ccb->ccb_len = sizeof(*blink); 1379 ccb->ccb_data = blink; 1380 ccb->ccb_xs = NULL; 1381 cmd = &ccb->ccb_cmd; 1382 cmd->tgt = htole32(CISS_CMD_MODE_PERIPH); 1383 cmd->tgt2 = 0; 1384 cmd->cdblen = 10; 1385 cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT; 1386 cmd->tmo = htole16(0); 1387 memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); 1388 cmd->cdb[0] = CISS_CMD_CTRL_SET; 1389 cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK; 1390 cmd->cdb[7] = sizeof(*blink) >> 8; /* biiiig endian */ 1391 cmd->cdb[8] = sizeof(*blink) & 0xff; 1392 1393 return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL); 1394 } 1395 1396 int 1397 ciss_create_sensors(struct ciss_softc *sc) 1398 { 1399 int i; 1400 int nsensors = sc->maxunits; 1401 1402 sc->sc_sme = sysmon_envsys_create(); 1403 sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors, 1404 M_DEVBUF, M_NOWAIT | M_ZERO); 1405 if (sc->sc_sensor == NULL) { 1406 aprint_error_dev(&sc->sc_dev, "can't allocate envsys_data"); 1407 return(ENOMEM); 1408 } 1409 1410 for (i = 0; i < nsensors; i++) { 1411 sc->sc_sensor[i].units = ENVSYS_DRIVE; 1412 sc->sc_sensor[i].monitor = true; 1413 /* Enable monitoring for drive state changes */ 1414 sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED; 1415 /* logical drives */ 1416 snprintf(sc->sc_sensor[i].desc, 1417 sizeof(sc->sc_sensor[i].desc), "%s:%d", 1418 device_xname(&sc->sc_dev), i); 1419 if (sysmon_envsys_sensor_attach(sc->sc_sme, 1420 &sc->sc_sensor[i])) 1421 goto out; 1422 } 1423 1424 sc->sc_sme->sme_name = device_xname(&sc->sc_dev); 1425 sc->sc_sme->sme_cookie = sc; 1426 sc->sc_sme->sme_refresh = ciss_sensor_refresh; 1427 if (sysmon_envsys_register(sc->sc_sme)) { 1428 printf("%s: unable to register with sysmon\n", device_xname(&sc->sc_dev)); 1429 return(1); 1430 } 1431 return (0); 1432 1433 out: 1434 free(sc->sc_sensor, M_DEVBUF); 1435 sysmon_envsys_destroy(sc->sc_sme); 1436 return EINVAL; 1437 } 1438 1439 void 1440 ciss_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 1441 { 1442 struct ciss_softc *sc = sme->sme_cookie; 1443 struct bioc_vol bv; 1444 1445 if (edata->sensor >= sc->maxunits) 1446 return; 1447 1448 memset(&bv, 0, sizeof(bv)); 1449 bv.bv_volid = edata->sensor; 1450 if (ciss_ioctl_vol(sc, &bv)) { 1451 return; 1452 } 1453 1454 switch(bv.bv_status) { 1455 case BIOC_SVOFFLINE: 1456 edata->value_cur = ENVSYS_DRIVE_FAIL; 1457 edata->state = ENVSYS_SCRITICAL; 1458 break; 1459 1460 case BIOC_SVDEGRADED: 1461 edata->value_cur = ENVSYS_DRIVE_PFAIL; 1462 edata->state = ENVSYS_SCRITICAL; 1463 break; 1464 1465 case BIOC_SVSCRUB: 1466 case BIOC_SVONLINE: 1467 edata->value_cur = ENVSYS_DRIVE_ONLINE; 1468 edata->state = ENVSYS_SVALID; 1469 break; 1470 1471 case BIOC_SVREBUILD: 1472 case BIOC_SVBUILDING: 1473 edata->value_cur = ENVSYS_DRIVE_REBUILD; 1474 edata->state = ENVSYS_SVALID; 1475 break; 1476 1477 case BIOC_SVINVALID: 1478 /* FALLTRHOUGH */ 1479 default: 1480 edata->value_cur = 0; /* unknown */ 1481 edata->state = ENVSYS_SINVALID; 1482 } 1483 } 1484 #endif /* NBIO > 0 */ 1485