Note that this is the second version of this patch. Apply by doing: cd /usr/src patch -p0 < 008_twe.patch And then rebuild your kernel. Index: sys/dev/ic/twe.c =================================================================== RCS file: /cvs/src/sys/dev/ic/twe.c,v retrieving revision 1.9 retrieving revision 1.9.2.2 diff -u -r1.9 -r1.9.2.2 --- sys/dev/ic/twe.c 2001/03/14 02:21:32 1.9 +++ sys/dev/ic/twe.c 2001/05/22 23:00:23 1.9.2.2 @@ -1,7 +1,7 @@ -/* $OpenBSD: twe.c,v 1.9 2001/03/14 02:21:32 mickey Exp $ */ +/* $OpenBSD: twe.c,v 1.9.2.2 2001/05/22 23:00:23 jason Exp $ */ /* - * Copyright (c) 2000 Michael Shalayeff. All rights reserved. + * Copyright (c) 2000, 2001 Michael Shalayeff. All rights reserved. * * The SCSI emulation layer is derived from gdt(4) driver, * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -33,7 +33,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#undef TWE_DEBUG +/* #define TWE_DEBUG */ #include #include @@ -114,13 +114,16 @@ struct twe_softc *sc; { register struct twe_ccb *ccb; - /* TODO: traverse the ccbs and destroy the maps */ - for (ccb = &sc->sc_ccbs[TWE_MAXCMDS - 1]; ccb >= sc->sc_ccbs; ccb--) - if (ccb->ccb_dmamap) - bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap); - if (sc->sc_cmdmap != NULL) + if (sc->sc_cmdmap != NULL) { bus_dmamap_destroy(sc->dmat, sc->sc_cmdmap); - bus_dmamem_free(sc->dmat, &sc->sc_cmdseg, 1); + /* traverse the ccbs and destroy the maps */ + for (ccb = &sc->sc_ccbs[TWE_MAXCMDS - 1]; ccb >= sc->sc_ccbs; ccb--) + if (ccb->ccb_dmamap) + bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap); + } + bus_dmamem_unmap(sc->dmat, sc->sc_cmds, + sizeof(struct twe_cmd) * TWE_MAXCMDS); + bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1); } int @@ -137,19 +140,21 @@ u_int32_t status; int error, i, retry, nunits, nseg; const char *errstr; + twe_lock_t lock; error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS, - PAGE_SIZE, 0, &sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT); + PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT); if (error) { printf(": cannot allocate commands (%d)\n", error); return (1); } - error = bus_dmamem_map(sc->dmat, &sc->sc_cmdseg, nseg, + error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg, sizeof(struct twe_cmd) * TWE_MAXCMDS, (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT); if (error) { printf(": cannot map commands (%d)\n", error); + bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1); return (1); } @@ -349,11 +354,14 @@ cap->table_id = TWE_PARAM_UI + i; cap->param_id = 4; cap->param_size = 4; /* 4 bytes */ + lock = TWE_LOCK_TWE(sc); if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) { + TWE_UNLOCK_TWE(sc, lock); printf("%s: error fetching capacity for unit %d\n", sc->sc_dev.dv_xname, i); continue; } + TWE_UNLOCK_TWE(sc, lock); nunits++; sc->sc_hdr[i].hd_present = 1; @@ -402,24 +410,26 @@ bus_dmamap_t dmap; struct twe_cmd *cmd; struct twe_segs *sgp; - int error, i, nseg; + int error, i; if (ccb->ccb_data && ((u_long)ccb->ccb_data & (TWE_ALIGN - 1))) { TWE_DPRINTF(TWE_D_DMA, ("data=%p is unaligned ",ccb->ccb_data)); ccb->ccb_realdata = ccb->ccb_data; - error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, - PAGE_SIZE, 0, &ccb->ccb_2bseg, 1, &nseg, BUS_DMA_NOWAIT); + error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, PAGE_SIZE, + 0, ccb->ccb_2bseg, TWE_MAXOFFSETS, &ccb->ccb_2nseg, + BUS_DMA_NOWAIT); if (error) { - TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed ")); + TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", error)); twe_put_ccb(ccb); return (ENOMEM); } - error = bus_dmamem_map(sc->dmat, &ccb->ccb_2bseg, nseg, + error = bus_dmamem_map(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg, ccb->ccb_length, (caddr_t *)&ccb->ccb_data, BUS_DMA_NOWAIT); if (error) { - TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed ")); + TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error)); + bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg); twe_put_ccb(ccb); return (ENOMEM); } @@ -440,6 +450,12 @@ else printf("error %d loading dma map\n", error); + if (ccb->ccb_realdata) { + bus_dmamem_unmap(sc->dmat, ccb->ccb_data, + ccb->ccb_length); + bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, + ccb->ccb_2nseg); + } twe_put_ccb(ccb); return error; } @@ -483,8 +499,14 @@ if ((error = twe_start(ccb, wait))) { bus_dmamap_unload(sc->dmat, dmap); + if (ccb->ccb_realdata) { + bus_dmamem_unmap(sc->dmat, ccb->ccb_data, + ccb->ccb_length); + bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, + ccb->ccb_2nseg); + } twe_put_ccb(ccb); - return error; + return (error); } return wait? twe_complete(ccb) : 0; @@ -544,10 +566,11 @@ struct twe_ccb *ccb; { struct twe_softc *sc = ccb->ccb_sc; + struct scsi_xfer *xs = ccb->ccb_xs; u_int32_t status; int i; - for (i = 100000; i--; DELAY(10)) { + for (i = 100 * (xs? xs->timeout : 35000); i--; DELAY(10)) { status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS); /* TWE_DPRINTF(TWE_D_CMD, ("twe_intr stat=%b ", status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */ @@ -583,6 +606,7 @@ struct twe_ccb *ccb = &sc->sc_ccbs[idx]; struct twe_cmd *cmd = ccb->ccb_cmd; struct scsi_xfer *xs = ccb->ccb_xs; + bus_dmamap_t dmap; twe_lock_t lock; TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", idx)); @@ -593,28 +617,26 @@ return 1; } + dmap = ccb->ccb_dmamap; if (xs) { if (xs->cmd->opcode != PREVENT_ALLOW && xs->cmd->opcode != SYNCHRONIZE_CACHE) { - bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, + bus_dmamap_sync(sc->dmat, dmap, (xs->flags & SCSI_DATA_IN) ? - BUS_DMASYNC_POSTREAD : - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmat, dmap); } } else { - switch (cmd->cmd_op) { + switch (letoh16(cmd->cmd_op)) { case TWE_CMD_GPARAM: case TWE_CMD_READ: - bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); + bus_dmamap_sync(sc->dmat, dmap, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->dmat, dmap); break; case TWE_CMD_SPARAM: case TWE_CMD_WRITE: - bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); + bus_dmamap_sync(sc->dmat, dmap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmat, dmap); break; default: /* no data */ @@ -623,9 +645,8 @@ if (ccb->ccb_realdata) { bcopy(ccb->ccb_data, ccb->ccb_realdata, ccb->ccb_length); - bus_dmamem_free(sc->dmat, &ccb->ccb_2bseg, 1); - ccb->ccb_data = ccb->ccb_realdata; - ccb->ccb_realdata = NULL; + bus_dmamem_unmap(sc->dmat, ccb->ccb_data, ccb->ccb_length); + bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg); } lock = TWE_LOCK_TWE(sc); @@ -848,7 +869,7 @@ cmd->cmd_op = op; cmd->cmd_flags = flags; cmd->cmd_io.count = htole16(blockcnt); - cmd->cmd_io.lba = blockno; + cmd->cmd_io.lba = htole32(blockno); if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)? BUS_DMA_NOWAIT : BUS_DMA_WAITOK), xs->flags & SCSI_POLL))) { @@ -958,9 +979,10 @@ u_int16_t aen; /* - * we no attentions of interest right now. + * we know no attentions of interest right now. * one of those would be mirror degradation i think. - * or, what else exist in there? maybe 3ware can answer that. + * or, what else exists in there? + * maybe 3ware can answer that? */ bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL, TWE_CTRL_CATTNI); Index: sys/dev/ic/twevar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/twevar.h,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -u -r1.2 -r1.2.2.1 --- sys/dev/ic/twevar.h 2001/02/19 20:48:02 1.2 +++ sys/dev/ic/twevar.h 2001/05/11 04:49:50 1.2.2.1 @@ -1,4 +1,4 @@ -/* $OpenBSD: twevar.h,v 1.2 2001/02/19 20:48:02 mickey Exp $ */ +/* $OpenBSD: twevar.h,v 1.2.2.1 2001/05/11 04:49:50 jason Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -46,7 +46,8 @@ void *ccb_data; void *ccb_realdata; bus_dmamap_t ccb_dmamap; - bus_dma_segment_t ccb_2bseg; + bus_dma_segment_t ccb_2bseg[TWE_MAXOFFSETS]; + int ccb_2nseg; }; typedef TAILQ_HEAD(twe_queue_head, twe_ccb) twe_queue_head; @@ -62,7 +63,7 @@ void *sc_cmds; bus_dmamap_t sc_cmdmap; - bus_dma_segment_t sc_cmdseg; + bus_dma_segment_t sc_cmdseg[1]; struct twe_ccb sc_ccbs[TWE_MAXCMDS]; twe_queue_head sc_free_ccb; twe_queue_head sc_ccbq; @@ -88,5 +89,3 @@ void tweminphys __P((struct buf *bp)); int twe_attach __P((struct twe_softc *)); int twe_intr __P((void *)); - -