[BACK]Return to ciss.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/ciss.c, Revision 1.1

1.1     ! nbrk        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

CVSweb