[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

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