The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/ciss.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 3c9cf69ec6ccc0af010d1d62d64765dc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.