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