root/dev/ic/ciss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ciss_get_ccb
  2. ciss_put_ccb
  3. ciss_attach
  4. ciss_shutdown
  5. cissminphys
  6. ciss_cmd
  7. ciss_done
  8. ciss_error
  9. ciss_inq
  10. ciss_ldmap
  11. ciss_sync
  12. ciss_scsi_raw_cmd
  13. ciss_scsi_cmd
  14. ciss_intr
  15. ciss_heartbeat
  16. ciss_kthread
  17. ciss_scsi_ioctl
  18. ciss_ioctl
  19. ciss_sensors
  20. ciss_ldid
  21. ciss_ldstat
  22. ciss_pdid
  23. ciss_pdscan
  24. ciss_blink

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

/* [<][>][^][v][top][bottom][index][help] */