Pull thorpej-bus-dma branch into mainline.
This commit is contained in:
parent
ef7d5776d0
commit
fbc0df0a1a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ahb.c,v 1.8 1997/03/28 23:47:14 mycroft Exp $ */
|
||||
/* $NetBSD: ahb.c,v 1.9 1997/06/06 23:30:02 thorpej Exp $ */
|
||||
|
||||
#undef AHBDEBUG
|
||||
#ifdef DDB
|
||||
|
@ -7,6 +7,43 @@
|
|||
#define integrate static inline
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
*
|
||||
|
@ -83,13 +120,14 @@
|
|||
#define ECB_HASH_SHIFT 9
|
||||
#define ECB_HASH(x) ((((long)(x))>>ECB_HASH_SHIFT) & (ECB_HASH_SIZE - 1))
|
||||
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
#define AHB_MAXXFER ((AHB_NSEG - 1) << PGSHIFT)
|
||||
|
||||
struct ahb_softc {
|
||||
struct device sc_dev;
|
||||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
void *sc_ih;
|
||||
|
||||
struct ahb_ecb *sc_ecbhash[ECB_HASH_SIZE];
|
||||
|
@ -117,6 +155,7 @@ void ahbminphys __P((struct buf *));
|
|||
int ahb_scsi_cmd __P((struct scsi_xfer *));
|
||||
int ahb_poll __P((struct ahb_softc *, struct scsi_xfer *, int));
|
||||
void ahb_timeout __P((void *));
|
||||
int ahb_create_ecbs __P((struct ahb_softc *));
|
||||
|
||||
integrate void ahb_reset_ecb __P((struct ahb_softc *, struct ahb_ecb *));
|
||||
integrate void ahb_init_ecb __P((struct ahb_softc *, struct ahb_ecb *));
|
||||
|
@ -136,7 +175,11 @@ struct scsi_device ahb_dev = {
|
|||
NULL, /* Use default 'done' routine */
|
||||
};
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int ahbmatch __P((struct device *, void *, void *));
|
||||
#else
|
||||
int ahbmatch __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void ahbattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach ahb_ca = {
|
||||
|
@ -149,6 +192,9 @@ struct cfdriver ahb_cd = {
|
|||
|
||||
#define AHB_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
|
||||
|
||||
/* XXX Should put this in a better place. */
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
/*
|
||||
* Check the slots looking for a board we recognise
|
||||
* If we find one, note it's address (slot) and call
|
||||
|
@ -157,7 +203,12 @@ struct cfdriver ahb_cd = {
|
|||
int
|
||||
ahbmatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *match;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct eisa_attach_args *ea = aux;
|
||||
bus_space_tag_t iot = ea->ea_iot;
|
||||
|
@ -217,6 +268,7 @@ ahbattach(parent, self, aux)
|
|||
|
||||
sc->sc_iot = iot;
|
||||
sc->sc_ioh = ioh;
|
||||
sc->sc_dmat = ea->ea_dmat;
|
||||
if (ahb_find(iot, ioh, &apd))
|
||||
panic("ahbattach: ahb_find failed!");
|
||||
|
||||
|
@ -284,7 +336,12 @@ ahb_send_mbox(sc, opcode, ecb)
|
|||
Debugger();
|
||||
}
|
||||
|
||||
bus_space_write_4(iot, ioh, MBOXOUT0, KVTOPHYS(ecb)); /* don't know this will work */
|
||||
/*
|
||||
* don't know if this will work.
|
||||
* XXX WHAT DOES THIS COMMENT MEAN?! --thorpej
|
||||
*/
|
||||
bus_space_write_4(iot, ioh, MBOXOUT0,
|
||||
ecb->dmamap_self->dm_segs[0].ds_addr);
|
||||
bus_space_write_1(iot, ioh, ATTN, opcode | ecb->xs->sc_link->target);
|
||||
|
||||
if ((ecb->xs->flags & SCSI_POLL) == 0)
|
||||
|
@ -433,25 +490,87 @@ ahb_free_ecb(sc, ecb)
|
|||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a set of ecbs and add them to the free list.
|
||||
*/
|
||||
integrate void
|
||||
ahb_init_ecb(sc, ecb)
|
||||
struct ahb_softc *sc;
|
||||
struct ahb_ecb *ecb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
int hashnum;
|
||||
|
||||
/*
|
||||
* XXX Should we put a DIAGNOSTIC check for multiple
|
||||
* XXX ECB inits here?
|
||||
*/
|
||||
|
||||
bzero(ecb, sizeof(struct ahb_ecb));
|
||||
|
||||
/*
|
||||
* Create the DMA maps for this ECB.
|
||||
*/
|
||||
if (bus_dmamap_create(dmat, sizeof(struct ahb_ecb), 1,
|
||||
sizeof(struct ahb_ecb), 0, BUS_DMA_NOWAIT, &ecb->dmamap_self) ||
|
||||
|
||||
/* XXX What's a good value for this? */
|
||||
bus_dmamap_create(dmat, AHB_MAXXFER, AHB_NSEG, AHB_MAXXFER,
|
||||
0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ecb->dmamap_xfer))
|
||||
panic("ahb_init_ecb: can't create DMA maps");
|
||||
|
||||
/*
|
||||
* Load the permanent DMA maps.
|
||||
*/
|
||||
if (bus_dmamap_load(dmat, ecb->dmamap_self, ecb,
|
||||
sizeof(struct ahb_ecb), NULL, BUS_DMA_NOWAIT))
|
||||
panic("ahb_init_ecb: can't load permanent maps");
|
||||
|
||||
/*
|
||||
* put in the phystokv hash table
|
||||
* Never gets taken out.
|
||||
*/
|
||||
ecb->hashkey = KVTOPHYS(ecb);
|
||||
ecb->hashkey = ecb->dmamap_self->dm_segs[0].ds_addr;
|
||||
hashnum = ECB_HASH(ecb->hashkey);
|
||||
ecb->nexthash = sc->sc_ecbhash[hashnum];
|
||||
sc->sc_ecbhash[hashnum] = ecb;
|
||||
ahb_reset_ecb(sc, ecb);
|
||||
}
|
||||
|
||||
int
|
||||
ahb_create_ecbs(sc)
|
||||
struct ahb_softc *sc;
|
||||
{
|
||||
bus_dma_segment_t seg;
|
||||
bus_size_t size;
|
||||
struct ahb_ecb *ecb;
|
||||
int rseg, error;
|
||||
|
||||
size = NBPG;
|
||||
error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
|
||||
(caddr_t *)&ecb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
|
||||
if (error) {
|
||||
bus_dmamem_free(sc->sc_dmat, &seg, rseg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
bzero(ecb, size);
|
||||
while (size > sizeof(struct ahb_ecb)) {
|
||||
ahb_init_ecb(sc, ecb);
|
||||
sc->sc_numecbs++;
|
||||
TAILQ_INSERT_TAIL(&sc->sc_free_ecb, ecb, chain);
|
||||
(caddr_t)ecb += ALIGN(sizeof(struct ahb_ecb));
|
||||
size -= ALIGN(sizeof(struct ahb_ecb));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a free ecb
|
||||
*
|
||||
|
@ -479,16 +598,12 @@ ahb_get_ecb(sc, flags)
|
|||
break;
|
||||
}
|
||||
if (sc->sc_numecbs < AHB_ECB_MAX) {
|
||||
ecb = (struct ahb_ecb *) malloc(sizeof(struct ahb_ecb),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (!ecb) {
|
||||
printf("%s: can't malloc ecb\n",
|
||||
if (ahb_create_ecbs(sc)) {
|
||||
printf("%s: can't allocate ecbs\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto out;
|
||||
}
|
||||
ahb_init_ecb(sc, ecb);
|
||||
sc->sc_numecbs++;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if ((flags & SCSI_NOSLEEP) != 0)
|
||||
goto out;
|
||||
|
@ -530,10 +645,23 @@ ahb_done(sc, ecb)
|
|||
struct ahb_softc *sc;
|
||||
struct ahb_ecb *ecb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct scsi_sense_data *s1, *s2;
|
||||
struct scsi_xfer *xs = ecb->xs;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahb_done\n"));
|
||||
|
||||
/*
|
||||
* If we were a data transfer, unload the map that described
|
||||
* the data buffer.
|
||||
*/
|
||||
if (xs->datalen) {
|
||||
bus_dmamap_sync(dmat, ecb->dmamap_xfer,
|
||||
(xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, ecb->dmamap_xfer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, put the results of the operation
|
||||
* into the xfer and call whoever started it
|
||||
|
@ -689,8 +817,8 @@ ahbminphys(bp)
|
|||
struct buf *bp;
|
||||
{
|
||||
|
||||
if (bp->b_bcount > ((AHB_NSEG - 1) << PGSHIFT))
|
||||
bp->b_bcount = ((AHB_NSEG - 1) << PGSHIFT);
|
||||
if (bp->b_bcount > AHB_MAXXFER)
|
||||
bp->b_bcount = AHB_MAXXFER;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
|
@ -704,14 +832,12 @@ ahb_scsi_cmd(xs)
|
|||
{
|
||||
struct scsi_link *sc_link = xs->sc_link;
|
||||
struct ahb_softc *sc = sc_link->adapter_softc;
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct ahb_ecb *ecb;
|
||||
struct ahb_dma_seg *sg;
|
||||
int seg; /* scatter gather seg being worked on */
|
||||
u_long thiskv, thisphys, nextphys;
|
||||
int bytes_this_seg, bytes_this_page, datalen, flags;
|
||||
int s;
|
||||
int error, seg, flags, s;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("ahb_scsi_cmd\n"));
|
||||
|
||||
/*
|
||||
* get a ecb (mbox-out) to use. If the transfer
|
||||
* is from a buf (possibly from interrupt time)
|
||||
|
@ -759,96 +885,65 @@ ahb_scsi_cmd(xs)
|
|||
ecb->opt1 = ECB_SES /*| ECB_DSB*/ | ECB_ARS;
|
||||
ecb->opt2 = sc_link->lun | ECB_NRB;
|
||||
bcopy(xs->cmd, &ecb->scsi_cmd, ecb->scsi_cmd_length = xs->cmdlen);
|
||||
ecb->sense_ptr = KVTOPHYS(&ecb->ecb_sense);
|
||||
ecb->sense_ptr = ecb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct ahb_ecb, ecb_sense);
|
||||
ecb->req_sense_length = sizeof(ecb->ecb_sense);
|
||||
ecb->status = KVTOPHYS(&ecb->ecb_status);
|
||||
ecb->status = ecb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct ahb_ecb, ecb_status);
|
||||
ecb->ecb_status.host_stat = 0x00;
|
||||
ecb->ecb_status.target_stat = 0x00;
|
||||
|
||||
if (xs->datalen) {
|
||||
sg = ecb->ahb_dma;
|
||||
seg = 0;
|
||||
#ifdef TFS
|
||||
/*
|
||||
* Map the DMA transfer.
|
||||
*/
|
||||
#ifdef TFS
|
||||
if (flags & SCSI_DATA_UIO) {
|
||||
struct iovec *iovp = ((struct uio *) xs->data)->uio_iov;
|
||||
datalen = ((struct uio *) xs->data)->uio_iovcnt;
|
||||
xs->datalen = 0;
|
||||
while (datalen && seg < AHB_NSEG) {
|
||||
sg->seg_addr = (physaddr)iovp->iov_base;
|
||||
sg->seg_len = iovp->iov_len;
|
||||
xs->datalen += iovp->iov_len;
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
|
||||
iovp->iov_len, iovp->iov_base));
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
datalen--;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /*TFS */
|
||||
error = bus_dmamap_load_uio(sc->sc_dmat,
|
||||
ecb->dmamap_xfer, (struct uio *)xs->data,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
} else
|
||||
#endif /* TFS */
|
||||
{
|
||||
/*
|
||||
* Set up the scatter gather block
|
||||
*/
|
||||
SC_DEBUG(sc_link, SDEV_DB4,
|
||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
||||
datalen = xs->datalen;
|
||||
thiskv = (long) xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
||||
while (datalen && seg < AHB_NSEG) {
|
||||
bytes_this_seg = 0;
|
||||
|
||||
/* put in the base address */
|
||||
sg->seg_addr = thisphys;
|
||||
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
while (datalen && thisphys == nextphys) {
|
||||
/*
|
||||
* This page is contiguous (physically)
|
||||
* with the the last, just extend the
|
||||
* length
|
||||
*/
|
||||
/* how far to the end of the page */
|
||||
nextphys = (thisphys & ~PGOFSET) + NBPG;
|
||||
bytes_this_page = nextphys - thisphys;
|
||||
/**** or the data ****/
|
||||
bytes_this_page = min(bytes_this_page,
|
||||
datalen);
|
||||
bytes_this_seg += bytes_this_page;
|
||||
datalen -= bytes_this_page;
|
||||
|
||||
/* get more ready for the next page */
|
||||
thiskv = (thiskv & ~PGOFSET) + NBPG;
|
||||
if (datalen)
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
}
|
||||
/*
|
||||
* next page isn't contiguous, finish the seg
|
||||
*/
|
||||
SC_DEBUGN(sc_link, SDEV_DB4,
|
||||
("(0x%x)", bytes_this_seg));
|
||||
sg->seg_len = bytes_this_seg;
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
error = bus_dmamap_load(sc->sc_dmat,
|
||||
ecb->dmamap_xfer, xs->data, xs->datalen, NULL,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
}
|
||||
/*end of iov/kv decision */
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
|
||||
if (datalen) {
|
||||
/*
|
||||
* there's still data, must have run out of segs!
|
||||
*/
|
||||
printf("%s: ahb_scsi_cmd, more than %d dma segs\n",
|
||||
sc->sc_dev.dv_xname, AHB_NSEG);
|
||||
|
||||
if (error) {
|
||||
if (error == EFBIG) {
|
||||
printf("%s: ahb_scsi_cmd, more than %d"
|
||||
" dma segments\n",
|
||||
sc->sc_dev.dv_xname, AHB_NSEG);
|
||||
} else {
|
||||
printf("%s: ahb_scsi_cmd, error %d loading"
|
||||
" dma map\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
ecb->data_addr = KVTOPHYS(ecb->ahb_dma);
|
||||
ecb->data_length = seg * sizeof(struct ahb_dma_seg);
|
||||
|
||||
bus_dmamap_sync(dmat, ecb->dmamap_xfer,
|
||||
(flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/*
|
||||
* Load the hardware scatter/gather map with the
|
||||
* contents of the DMA map.
|
||||
*/
|
||||
for (seg = 0; seg < ecb->dmamap_xfer->dm_nsegs; seg++) {
|
||||
ecb->ahb_dma[seg].seg_addr =
|
||||
ecb->dmamap_xfer->dm_segs[seg].ds_addr;
|
||||
ecb->ahb_dma[seg].seg_len =
|
||||
ecb->dmamap_xfer->dm_segs[seg].ds_len;
|
||||
}
|
||||
|
||||
ecb->data_addr = ecb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct ahb_ecb, ahb_dma);
|
||||
ecb->data_length = ecb->dmamap_xfer->dm_nsegs *
|
||||
sizeof(struct ahb_dma_seg);
|
||||
ecb->opt1 |= ECB_S_G;
|
||||
} else { /* No data xfer, use non S/G values */
|
||||
ecb->data_addr = (physaddr)0;
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
/* $NetBSD: ahbreg.h,v 1.2 1996/09/01 00:54:34 mycroft Exp $ */
|
||||
/* $NetBSD: ahbreg.h,v 1.3 1997/06/06 23:30:03 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
|
||||
|
@ -215,4 +252,21 @@ struct ahb_ecb {
|
|||
#define ECB_IMMED 0x04
|
||||
#define ECB_IMMED_FAIL 0x08
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* DMA maps used by the ECB. These maps are created
|
||||
* in ahb_init_ecb().
|
||||
*/
|
||||
|
||||
/*
|
||||
* This DMA map maps an individual ECB. This map is
|
||||
* permanently loaded in ahb_init_ecb().
|
||||
*/
|
||||
bus_dmamap_t dmamap_self;
|
||||
|
||||
/*
|
||||
* This DMA map maps the buffer involved in the transfer.
|
||||
* Its contents are loaded into "ahb_dma" above.
|
||||
*/
|
||||
bus_dmamap_t dmamap_xfer;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bha_eisa.c,v 1.7 1997/03/28 23:47:15 mycroft Exp $ */
|
||||
/* $NetBSD: bha_eisa.c,v 1.8 1997/06/06 23:30:04 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
|
@ -127,9 +127,12 @@ bha_eisa_attach(parent, self, aux)
|
|||
|
||||
sc->sc_iot = iot;
|
||||
sc->sc_ioh = ioh;
|
||||
sc->sc_dmat = ea->ea_dmat;
|
||||
if (!bha_find(iot, ioh, &bpd))
|
||||
panic("bha_eisa_attach: bha_find failed");
|
||||
|
||||
sc->sc_dmaflags = 0;
|
||||
|
||||
if (eisa_intr_map(ec, bpd.sc_irq, &ih)) {
|
||||
printf("%s: couldn't map interrupt (%d)\n",
|
||||
sc->sc_dev.dv_xname, bpd.sc_irq);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: eisa.c,v 1.16 1996/12/05 01:25:36 cgd Exp $ */
|
||||
/* $NetBSD: eisa.c,v 1.17 1997/06/06 23:30:06 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996 Christopher G. Demetriou
|
||||
|
@ -146,6 +146,7 @@ eisaattach(parent, self, aux)
|
|||
{
|
||||
struct eisabus_attach_args *eba = aux;
|
||||
bus_space_tag_t iot, memt;
|
||||
bus_dma_tag_t dmat;
|
||||
eisa_chipset_tag_t ec;
|
||||
int slot, maxnslots;
|
||||
|
||||
|
@ -155,6 +156,7 @@ eisaattach(parent, self, aux)
|
|||
iot = eba->eba_iot;
|
||||
memt = eba->eba_memt;
|
||||
ec = eba->eba_ec;
|
||||
dmat = eba->eba_dmat;
|
||||
|
||||
/*
|
||||
* Search for and attach subdevices.
|
||||
|
@ -172,6 +174,7 @@ eisaattach(parent, self, aux)
|
|||
ea.ea_iot = iot;
|
||||
ea.ea_memt = memt;
|
||||
ea.ea_ec = ec;
|
||||
ea.ea_dmat = dmat;
|
||||
ea.ea_slot = slot;
|
||||
slotaddr = EISA_SLOT_ADDR(slot);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: eisavar.h,v 1.10 1996/10/21 22:31:03 thorpej Exp $ */
|
||||
/* $NetBSD: eisavar.h,v 1.11 1997/06/06 23:30:07 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996 Christopher G. Demetriou
|
||||
|
@ -72,6 +72,7 @@ struct eisabus_attach_args {
|
|||
char *eba_busname; /* XXX should be common */
|
||||
bus_space_tag_t eba_iot; /* eisa i/o space tag */
|
||||
bus_space_tag_t eba_memt; /* eisa mem space tag */
|
||||
bus_dma_tag_t eba_dmat; /* DMA tag */
|
||||
eisa_chipset_tag_t eba_ec;
|
||||
};
|
||||
|
||||
|
@ -81,6 +82,7 @@ struct eisabus_attach_args {
|
|||
struct eisa_attach_args {
|
||||
bus_space_tag_t ea_iot; /* eisa i/o space tag */
|
||||
bus_space_tag_t ea_memt; /* eisa mem space tag */
|
||||
bus_dma_tag_t ea_dmat; /* DMA tag */
|
||||
eisa_chipset_tag_t ea_ec;
|
||||
|
||||
eisa_slot_t ea_slot;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uha_eisa.c,v 1.7 1997/03/29 02:32:30 mycroft Exp $ */
|
||||
/* $NetBSD: uha_eisa.c,v 1.8 1997/06/06 23:30:09 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
|
@ -52,7 +52,11 @@
|
|||
#define UHA_EISA_SLOT_OFFSET 0xc80
|
||||
#define UHA_EISA_IOSIZE 0x020
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int uha_eisa_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int uha_eisa_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void uha_eisa_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach uha_eisa_ca = {
|
||||
|
@ -62,7 +66,6 @@ struct cfattach uha_eisa_ca = {
|
|||
#ifndef DDB
|
||||
#define Debugger() panic("should call debugger here (uha_eisa.c)")
|
||||
#endif /* ! DDB */
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
|
||||
int u24_find __P((bus_space_tag_t, bus_space_handle_t,
|
||||
struct uha_probe_data *));
|
||||
|
@ -79,7 +82,12 @@ void u24_init __P((struct uha_softc *));
|
|||
int
|
||||
uha_eisa_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *match;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct eisa_attach_args *ea = aux;
|
||||
bus_space_tag_t iot = ea->ea_iot;
|
||||
|
@ -112,6 +120,7 @@ uha_eisa_attach(parent, self, aux)
|
|||
struct eisa_attach_args *ea = aux;
|
||||
struct uha_softc *sc = (void *)self;
|
||||
bus_space_tag_t iot = ea->ea_iot;
|
||||
bus_dma_tag_t dmat = ea->ea_dmat;
|
||||
bus_space_handle_t ioh;
|
||||
struct uha_probe_data upd;
|
||||
eisa_chipset_tag_t ec = ea->ea_ec;
|
||||
|
@ -130,9 +139,12 @@ uha_eisa_attach(parent, self, aux)
|
|||
|
||||
sc->sc_iot = iot;
|
||||
sc->sc_ioh = ioh;
|
||||
sc->sc_dmat = dmat;
|
||||
if (!u24_find(iot, ioh, &upd))
|
||||
panic("uha_eisa_attach: u24_find failed!");
|
||||
|
||||
sc->sc_dmaflags = 0;
|
||||
|
||||
if (eisa_intr_map(ec, upd.sc_irq, &ih)) {
|
||||
printf("%s: couldn't map interrupt (%d)\n",
|
||||
sc->sc_dev.dv_xname, upd.sc_irq);
|
||||
|
@ -239,7 +251,8 @@ u24_start_mbox(sc, mscp)
|
|||
Debugger();
|
||||
}
|
||||
|
||||
bus_space_write_4(iot, ioh, U24_OGMPTR, KVTOPHYS(mscp));
|
||||
bus_space_write_4(iot, ioh, U24_OGMPTR,
|
||||
mscp->dmamap_self->dm_segs[0].ds_addr);
|
||||
if (mscp->flags & MSCP_ABORT)
|
||||
bus_space_write_1(iot, ioh, U24_OGMCMD, 0x80);
|
||||
else
|
||||
|
|
328
sys/dev/ic/aha.c
328
sys/dev/ic/aha.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aha.c,v 1.4 1997/03/28 23:47:08 mycroft Exp $ */
|
||||
/* $NetBSD: aha.c,v 1.5 1997/06/06 23:30:58 thorpej Exp $ */
|
||||
|
||||
#undef AHADIAG
|
||||
#ifdef DDB
|
||||
|
@ -7,6 +7,43 @@
|
|||
#define integrate static inline
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
*
|
||||
|
@ -76,7 +113,7 @@
|
|||
#define Debugger() panic("should call debugger here (aha1542.c)")
|
||||
#endif /* ! DDB */
|
||||
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
#define AHA_MAXXFER ((AHA_NSEG - 1) << PGSHIFT)
|
||||
|
||||
#ifdef AHADEBUG
|
||||
int aha_debug = 1;
|
||||
|
@ -100,6 +137,7 @@ void ahaminphys __P((struct buf *));
|
|||
int aha_scsi_cmd __P((struct scsi_xfer *));
|
||||
int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int));
|
||||
void aha_timeout __P((void *arg));
|
||||
int aha_create_ccbs __P((struct aha_softc *, void *, size_t));
|
||||
|
||||
struct scsi_adapter aha_switch = {
|
||||
aha_scsi_cmd,
|
||||
|
@ -123,6 +161,9 @@ struct cfdriver aha_cd = {
|
|||
#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
|
||||
#define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
|
||||
|
||||
/* XXX Should put this in a better place. */
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
/*
|
||||
* aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
|
||||
*
|
||||
|
@ -261,11 +302,12 @@ aha_attach(sc, apd)
|
|||
struct aha_probe_data *apd;
|
||||
{
|
||||
|
||||
aha_inquire_setup_information(sc);
|
||||
aha_init(sc);
|
||||
TAILQ_INIT(&sc->sc_free_ccb);
|
||||
TAILQ_INIT(&sc->sc_waiting_ccb);
|
||||
|
||||
aha_inquire_setup_information(sc);
|
||||
aha_init(sc);
|
||||
|
||||
/*
|
||||
* fill in the prototype scsi_link.
|
||||
*/
|
||||
|
@ -458,20 +500,92 @@ aha_init_ccb(sc, ccb)
|
|||
struct aha_softc *sc;
|
||||
struct aha_ccb *ccb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
int hashnum;
|
||||
|
||||
/*
|
||||
* XXX Should we put a DIAGNOSTIC check for multiple
|
||||
* XXX CCB inits here?
|
||||
*/
|
||||
|
||||
bzero(ccb, sizeof(struct aha_ccb));
|
||||
|
||||
/*
|
||||
* Create DMA maps for this CCB.
|
||||
*/
|
||||
if (bus_dmamap_create(dmat, sizeof(struct aha_ccb), 1,
|
||||
sizeof(struct aha_ccb), 0, BUS_DMA_NOWAIT, &ccb->dmamap_self) ||
|
||||
|
||||
/* XXX What's a good value for this? */
|
||||
bus_dmamap_create(dmat, AHA_MAXXFER, AHA_NSEG, AHA_MAXXFER,
|
||||
0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer))
|
||||
panic("aha_init_ccb: can't create DMA maps");
|
||||
|
||||
/*
|
||||
* Load the permanent DMA maps.
|
||||
*/
|
||||
if (bus_dmamap_load(dmat, ccb->dmamap_self, ccb,
|
||||
sizeof(struct aha_ccb), NULL, BUS_DMA_NOWAIT))
|
||||
panic("aha_init_ccb: can't load permanent maps");
|
||||
|
||||
/*
|
||||
* put in the phystokv hash table
|
||||
* Never gets taken out.
|
||||
*/
|
||||
ccb->hashkey = KVTOPHYS(ccb);
|
||||
ccb->hashkey = ccb->dmamap_self->dm_segs[0].ds_addr;
|
||||
hashnum = CCB_HASH(ccb->hashkey);
|
||||
ccb->nexthash = sc->sc_ccbhash[hashnum];
|
||||
sc->sc_ccbhash[hashnum] = ccb;
|
||||
aha_reset_ccb(sc, ccb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a set of ccbs and add them to the free list.
|
||||
*/
|
||||
int
|
||||
aha_create_ccbs(sc, mem, size)
|
||||
struct aha_softc *sc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
{
|
||||
bus_dma_segment_t seg;
|
||||
struct aha_ccb *ccb;
|
||||
int rseg, error;
|
||||
|
||||
if (sc->sc_numccbs >= AHA_CCB_MAX)
|
||||
return (0);
|
||||
|
||||
if ((ccb = mem) != NULL)
|
||||
goto have_mem;
|
||||
|
||||
size = NBPG;
|
||||
error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
|
||||
(caddr_t *)&ccb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
|
||||
if (error) {
|
||||
bus_dmamem_free(sc->sc_dmat, &seg, rseg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
have_mem:
|
||||
bzero(ccb, size);
|
||||
while (size > sizeof(struct aha_ccb)) {
|
||||
aha_init_ccb(sc, ccb);
|
||||
sc->sc_numccbs++;
|
||||
if (sc->sc_numccbs >= AHA_CCB_MAX)
|
||||
break;
|
||||
TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
|
||||
(caddr_t)ccb += ALIGN(sizeof(struct aha_ccb));
|
||||
size -= ALIGN(sizeof(struct aha_ccb));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a free ccb
|
||||
*
|
||||
|
@ -499,16 +613,12 @@ aha_get_ccb(sc, flags)
|
|||
break;
|
||||
}
|
||||
if (sc->sc_numccbs < AHA_CCB_MAX) {
|
||||
ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (!ccb) {
|
||||
printf("%s: can't malloc ccb\n",
|
||||
if (aha_create_ccbs(sc, NULL, 0)) {
|
||||
printf("%s: can't allocate ccbs\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto out;
|
||||
}
|
||||
aha_init_ccb(sc, ccb);
|
||||
sc->sc_numccbs++;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if ((flags & SCSI_NOSLEEP) != 0)
|
||||
goto out;
|
||||
|
@ -619,7 +729,7 @@ aha_start_ccbs(sc)
|
|||
#endif
|
||||
|
||||
/* Link ccb to mbo. */
|
||||
ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
|
||||
ltophys(ccb->dmamap_self->dm_segs[0].ds_addr, wmbo->ccb_addr);
|
||||
if (ccb->flags & CCB_ABORT)
|
||||
wmbo->cmd = AHA_MBO_ABORT;
|
||||
else
|
||||
|
@ -648,10 +758,23 @@ aha_done(sc, ccb)
|
|||
struct aha_softc *sc;
|
||||
struct aha_ccb *ccb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct scsi_sense_data *s1, *s2;
|
||||
struct scsi_xfer *xs = ccb->xs;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
|
||||
|
||||
/*
|
||||
* If we were a data transfer, unload the map that described
|
||||
* the data buffer.
|
||||
*/
|
||||
if (xs->datalen) {
|
||||
bus_dmamap_sync(dmat, ccb->dmamap_xfer,
|
||||
(xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, ccb->dmamap_xfer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, put the results of the operation
|
||||
* into the xfer and call whoever started it
|
||||
|
@ -814,10 +937,11 @@ aha_init(sc)
|
|||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
bus_dma_segment_t seg;
|
||||
struct aha_devices devices;
|
||||
struct aha_setup setup;
|
||||
struct aha_mailbox mailbox;
|
||||
int i;
|
||||
int i, rseg;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
|
@ -885,6 +1009,33 @@ aha_init(sc)
|
|||
setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the mailbox.
|
||||
*/
|
||||
if (bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1,
|
||||
&rseg, BUS_DMA_NOWAIT) ||
|
||||
bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
|
||||
(caddr_t *)&wmbx, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC))
|
||||
panic("aha_init: can't create or map mailbox");
|
||||
|
||||
/*
|
||||
* Since DMA memory allocation is always rounded up to a
|
||||
* page size, create some ccbs from the leftovers.
|
||||
*/
|
||||
if (aha_create_ccbs(sc, ((caddr_t)wmbx) +
|
||||
ALIGN(sizeof(struct aha_mbx)),
|
||||
NBPG - ALIGN(sizeof(struct aha_mbx))))
|
||||
panic("aha_init: can't create ccbs");
|
||||
|
||||
/*
|
||||
* Create and load the mailbox DMA map.
|
||||
*/
|
||||
if (bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_mbx), 1,
|
||||
sizeof(struct aha_mbx), 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_mbox) ||
|
||||
bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox, wmbx,
|
||||
sizeof(struct aha_mbx), NULL, BUS_DMA_NOWAIT))
|
||||
panic("aha_init: can't create or load mailbox dma map");
|
||||
|
||||
/*
|
||||
* Set up initial mail box for round-robin operation.
|
||||
*/
|
||||
|
@ -899,7 +1050,7 @@ aha_init(sc)
|
|||
/* Initialize mail box. */
|
||||
mailbox.cmd.opcode = AHA_MBX_INIT;
|
||||
mailbox.cmd.nmbx = AHA_MBX_SIZE;
|
||||
ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
|
||||
ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, mailbox.cmd.addr);
|
||||
aha_cmd(iot, ioh, sc,
|
||||
sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
|
||||
0, (u_char *)0);
|
||||
|
@ -996,8 +1147,8 @@ ahaminphys(bp)
|
|||
struct buf *bp;
|
||||
{
|
||||
|
||||
if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT))
|
||||
bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT);
|
||||
if (bp->b_bcount > AHA_MAXXFER)
|
||||
bp->b_bcount = AHA_MAXXFER;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
|
@ -1011,15 +1162,9 @@ aha_scsi_cmd(xs)
|
|||
{
|
||||
struct scsi_link *sc_link = xs->sc_link;
|
||||
struct aha_softc *sc = sc_link->adapter_softc;
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct aha_ccb *ccb;
|
||||
struct aha_scat_gath *sg;
|
||||
int seg; /* scatter gather seg being worked on */
|
||||
u_long thiskv, thisphys, nextphys;
|
||||
int bytes_this_seg, bytes_this_page, datalen, flags;
|
||||
#ifdef TFS
|
||||
struct iovec *iovp;
|
||||
#endif
|
||||
int s;
|
||||
int error, seg, flags, s;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
|
||||
/*
|
||||
|
@ -1050,97 +1195,60 @@ aha_scsi_cmd(xs)
|
|||
}
|
||||
|
||||
if (xs->datalen) {
|
||||
sg = ccb->scat_gath;
|
||||
seg = 0;
|
||||
#ifdef TFS
|
||||
/*
|
||||
* Map the DMA transfer.
|
||||
*/
|
||||
#ifdef TFS
|
||||
if (flags & SCSI_DATA_UIO) {
|
||||
iovp = ((struct uio *)xs->data)->uio_iov;
|
||||
datalen = ((struct uio *)xs->data)->uio_iovcnt;
|
||||
xs->datalen = 0;
|
||||
while (datalen && seg < AHA_NSEG) {
|
||||
ltophys(iovp->iov_base, sg->seg_addr);
|
||||
ltophys(iovp->iov_len, sg->seg_len);
|
||||
xs->datalen += iovp->iov_len;
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
|
||||
iovp->iov_len, iovp->iov_base));
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
datalen--;
|
||||
}
|
||||
error = bus_dmamap_load_uio(dmat,
|
||||
ccb->dmamap_xfer, (struct uio *)xs->data,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
} else
|
||||
#endif /* TFS */
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Set up the scatter-gather block.
|
||||
*/
|
||||
SC_DEBUG(sc_link, SDEV_DB4,
|
||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
||||
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
||||
while (datalen && seg < AHA_NSEG) {
|
||||
bytes_this_seg = 0;
|
||||
|
||||
/* put in the base address */
|
||||
ltophys(thisphys, sg->seg_addr);
|
||||
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
while (datalen && thisphys == nextphys) {
|
||||
/*
|
||||
* This page is contiguous (physically)
|
||||
* with the the last, just extend the
|
||||
* length
|
||||
*/
|
||||
/* check it fits on the ISA bus */
|
||||
if (thisphys > 0xFFFFFF) {
|
||||
printf("%s: DMA beyond"
|
||||
" end of ISA\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto bad;
|
||||
}
|
||||
/* how far to the end of the page */
|
||||
nextphys = (thisphys & ~PGOFSET) + NBPG;
|
||||
bytes_this_page = nextphys - thisphys;
|
||||
/**** or the data ****/
|
||||
bytes_this_page = min(bytes_this_page,
|
||||
datalen);
|
||||
bytes_this_seg += bytes_this_page;
|
||||
datalen -= bytes_this_page;
|
||||
|
||||
/* get more ready for the next page */
|
||||
thiskv = (thiskv & ~PGOFSET) + NBPG;
|
||||
if (datalen)
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
}
|
||||
/*
|
||||
* next page isn't contiguous, finish the seg
|
||||
*/
|
||||
SC_DEBUGN(sc_link, SDEV_DB4,
|
||||
("(0x%x)", bytes_this_seg));
|
||||
ltophys(bytes_this_seg, sg->seg_len);
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
error = bus_dmamap_load(dmat,
|
||||
ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
}
|
||||
/* end of iov/kv decision */
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
|
||||
if (datalen) {
|
||||
/*
|
||||
* there's still data, must have run out of segs!
|
||||
*/
|
||||
printf("%s: aha_scsi_cmd, more than %d dma segs\n",
|
||||
sc->sc_dev.dv_xname, AHA_NSEG);
|
||||
|
||||
if (error) {
|
||||
if (error == EFBIG) {
|
||||
printf("%s: aha_scsi_cmd, more than %d"
|
||||
" dma segments\n",
|
||||
sc->sc_dev.dv_xname, AHA_NSEG);
|
||||
} else {
|
||||
printf("%s: aha_scsi_cmd, error %d loading"
|
||||
" dma map\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
|
||||
ltophys(seg * sizeof(struct aha_scat_gath), ccb->data_length);
|
||||
} else { /* No data xfer, use non S/G values */
|
||||
|
||||
bus_dmamap_sync(dmat, ccb->dmamap_xfer,
|
||||
(flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/*
|
||||
* Load the hardware scatter/gather map with the
|
||||
* contents of the DMA map.
|
||||
*/
|
||||
for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
|
||||
ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
|
||||
ccb->scat_gath[seg].seg_addr);
|
||||
ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
|
||||
ccb->scat_gath[seg].seg_len);
|
||||
}
|
||||
|
||||
ltophys(ccb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct aha_ccb, scat_gath), ccb->data_addr);
|
||||
ltophys(ccb->dmamap_xfer->dm_nsegs *
|
||||
sizeof(struct aha_scat_gath), ccb->data_length);
|
||||
} else {
|
||||
/*
|
||||
* No data xfer, use non S/G values.
|
||||
*/
|
||||
ltophys(0, ccb->data_addr);
|
||||
ltophys(0, ccb->data_length);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
/* $NetBSD: ahareg.h,v 1.2 1997/03/15 18:11:23 is Exp $ */
|
||||
/* $NetBSD: ahareg.h,v 1.3 1997/06/06 23:30:59 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
|
||||
|
@ -174,6 +211,23 @@ struct aha_ccb {
|
|||
#define CCB_SENDING 0x04
|
||||
#endif
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* DMA maps used by the CCB. These maps are created
|
||||
* in aha_init_ccb().
|
||||
*/
|
||||
|
||||
/*
|
||||
* This DMA map maps an individual CCB. This map is permanently
|
||||
* loaded in aha_init_ccb().
|
||||
*/
|
||||
bus_dmamap_t dmamap_self;
|
||||
|
||||
/*
|
||||
* This DMA map maps the buffer involved in the transfer.
|
||||
* Its contents are loaded into "scat_gath" above.
|
||||
*/
|
||||
bus_dmamap_t dmamap_xfer;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ahavar.h,v 1.3 1997/03/28 23:47:10 mycroft Exp $ */
|
||||
/* $NetBSD: ahavar.h,v 1.4 1997/06/06 23:31:00 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
|
@ -59,10 +59,12 @@ struct aha_softc {
|
|||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
bus_dmamap_t sc_dmamap_mbox; /* maps the mailbox */
|
||||
void *sc_ih;
|
||||
|
||||
struct aha_mbx sc_mbx; /* all our mailboxes */
|
||||
#define wmbx (&sc->sc_mbx)
|
||||
struct aha_mbx *sc_mbx; /* all our mailboxes */
|
||||
#define wmbx (sc->sc_mbx)
|
||||
struct aha_ccb *sc_ccbhash[CCB_HASH_SIZE];
|
||||
TAILQ_HEAD(, aha_ccb) sc_free_ccb, sc_waiting_ccb;
|
||||
int sc_numccbs, sc_mbofull;
|
||||
|
|
344
sys/dev/ic/bha.c
344
sys/dev/ic/bha.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bha.c,v 1.12 1997/04/11 01:34:25 thorpej Exp $ */
|
||||
/* $NetBSD: bha.c,v 1.13 1997/06/06 23:31:01 thorpej Exp $ */
|
||||
|
||||
#undef BHADIAG
|
||||
#ifdef DDB
|
||||
|
@ -7,6 +7,43 @@
|
|||
#define integrate static inline
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
*
|
||||
|
@ -76,14 +113,7 @@
|
|||
#define Debugger() panic("should call debugger here (bha.c)")
|
||||
#endif /* ! DDB */
|
||||
|
||||
#ifdef alpha /* XXX */
|
||||
/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
|
||||
extern vm_offset_t alpha_XXX_dmamap(vm_offset_t);
|
||||
#undef vtophys
|
||||
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t) va)
|
||||
#endif /* alpha */
|
||||
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
#define BHA_MAXXFER ((BHA_NSEG - 1) << PGSHIFT)
|
||||
|
||||
#ifdef BHADEBUG
|
||||
int bha_debug = 0;
|
||||
|
@ -102,11 +132,11 @@ void bha_collect_mbo __P((struct bha_softc *));
|
|||
void bha_start_ccbs __P((struct bha_softc *));
|
||||
void bha_done __P((struct bha_softc *, struct bha_ccb *));
|
||||
void bha_init __P((struct bha_softc *));
|
||||
void bha_inquire_setup_information __P((struct bha_softc *));
|
||||
void bhaminphys __P((struct buf *));
|
||||
int bha_scsi_cmd __P((struct scsi_xfer *));
|
||||
int bha_poll __P((struct bha_softc *, struct scsi_xfer *, int));
|
||||
void bha_timeout __P((void *arg));
|
||||
int bha_create_ccbs __P((struct bha_softc *, void *, size_t));
|
||||
|
||||
struct scsi_adapter bha_switch = {
|
||||
bha_scsi_cmd,
|
||||
|
@ -130,6 +160,9 @@ struct cfdriver bha_cd = {
|
|||
#define BHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
|
||||
#define BHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
|
||||
|
||||
/* XXX Should put this in a better place. */
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
/*
|
||||
* bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
|
||||
*
|
||||
|
@ -287,11 +320,16 @@ bha_attach(sc, bpd)
|
|||
sc->sc_link.openings = 4;
|
||||
sc->sc_link.max_target = bpd->sc_iswide ? 15 : 7;
|
||||
|
||||
bha_inquire_setup_information(sc);
|
||||
bha_init(sc);
|
||||
TAILQ_INIT(&sc->sc_free_ccb);
|
||||
TAILQ_INIT(&sc->sc_waiting_ccb);
|
||||
|
||||
bha_inquire_setup_information(sc);
|
||||
|
||||
printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
|
||||
sc->sc_model, sc->sc_firmware);
|
||||
|
||||
bha_init(sc);
|
||||
|
||||
/*
|
||||
* ask the adapter what subunits are present
|
||||
*/
|
||||
|
@ -473,20 +511,94 @@ bha_init_ccb(sc, ccb)
|
|||
struct bha_softc *sc;
|
||||
struct bha_ccb *ccb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
int hashnum;
|
||||
|
||||
/*
|
||||
* XXX Should we put a DIAGNOSTIC check for multiple
|
||||
* XXX CCB inits here?
|
||||
*/
|
||||
|
||||
bzero(ccb, sizeof(struct bha_ccb));
|
||||
|
||||
/*
|
||||
* Create DMA maps for this CCB.
|
||||
*/
|
||||
if (bus_dmamap_create(dmat, sizeof(struct bha_ccb), 1,
|
||||
sizeof(struct bha_ccb), 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
|
||||
&ccb->dmamap_self) ||
|
||||
|
||||
/* XXX What's a good value for this? */
|
||||
bus_dmamap_create(dmat, BHA_MAXXFER, BHA_NSEG, BHA_MAXXFER,
|
||||
0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
|
||||
&ccb->dmamap_xfer))
|
||||
panic("bha_init_ccb: can't create DMA maps");
|
||||
|
||||
/*
|
||||
* Load the permanent DMA maps.
|
||||
*/
|
||||
if (bus_dmamap_load(dmat, ccb->dmamap_self, ccb,
|
||||
sizeof(struct bha_ccb), NULL, BUS_DMA_NOWAIT))
|
||||
panic("bha_init_ccb: can't load permanent maps");
|
||||
|
||||
/*
|
||||
* put in the phystokv hash table
|
||||
* Never gets taken out.
|
||||
*/
|
||||
ccb->hashkey = KVTOPHYS(ccb);
|
||||
ccb->hashkey = ccb->dmamap_self->dm_segs[0].ds_addr;
|
||||
hashnum = CCB_HASH(ccb->hashkey);
|
||||
ccb->nexthash = sc->sc_ccbhash[hashnum];
|
||||
sc->sc_ccbhash[hashnum] = ccb;
|
||||
bha_reset_ccb(sc, ccb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a set of ccbs and add them to the free list.
|
||||
*/
|
||||
int
|
||||
bha_create_ccbs(sc, mem, size)
|
||||
struct bha_softc *sc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
{
|
||||
bus_dma_segment_t seg;
|
||||
struct bha_ccb *ccb;
|
||||
int rseg, error;
|
||||
|
||||
if (sc->sc_numccbs >= BHA_CCB_MAX)
|
||||
return (0);
|
||||
|
||||
if ((ccb = mem) != NULL)
|
||||
goto have_mem;
|
||||
|
||||
size = NBPG;
|
||||
error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
|
||||
(caddr_t *)&ccb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
|
||||
if (error) {
|
||||
bus_dmamem_free(sc->sc_dmat, &seg, rseg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
have_mem:
|
||||
bzero(ccb, size);
|
||||
while (size > sizeof(struct bha_ccb)) {
|
||||
bha_init_ccb(sc, ccb);
|
||||
sc->sc_numccbs++;
|
||||
if (sc->sc_numccbs >= BHA_CCB_MAX)
|
||||
break;
|
||||
TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
|
||||
(caddr_t)ccb += ALIGN(sizeof(struct bha_ccb));
|
||||
size -= ALIGN(sizeof(struct bha_ccb));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a free ccb
|
||||
*
|
||||
|
@ -514,16 +626,12 @@ bha_get_ccb(sc, flags)
|
|||
break;
|
||||
}
|
||||
if (sc->sc_numccbs < BHA_CCB_MAX) {
|
||||
ccb = (struct bha_ccb *) malloc(sizeof(struct bha_ccb),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (!ccb) {
|
||||
printf("%s: can't malloc ccb\n",
|
||||
if (bha_create_ccbs(sc, NULL, 0)) {
|
||||
printf("%s: can't allocate ccbs\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto out;
|
||||
}
|
||||
bha_init_ccb(sc, ccb);
|
||||
sc->sc_numccbs++;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if ((flags & SCSI_NOSLEEP) != 0)
|
||||
goto out;
|
||||
|
@ -634,7 +742,7 @@ bha_start_ccbs(sc)
|
|||
#endif
|
||||
|
||||
/* Link ccb to mbo. */
|
||||
ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
|
||||
ltophys(ccb->dmamap_self->dm_segs[0].ds_addr, wmbo->ccb_addr);
|
||||
if (ccb->flags & CCB_ABORT)
|
||||
wmbo->cmd = BHA_MBO_ABORT;
|
||||
else
|
||||
|
@ -663,10 +771,23 @@ bha_done(sc, ccb)
|
|||
struct bha_softc *sc;
|
||||
struct bha_ccb *ccb;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct scsi_sense_data *s1, *s2;
|
||||
struct scsi_xfer *xs = ccb->xs;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("bha_done\n"));
|
||||
|
||||
/*
|
||||
* If we were a data transfer, unload the map that described
|
||||
* the data buffer.
|
||||
*/
|
||||
if (xs->datalen) {
|
||||
bus_dmamap_sync(dmat, ccb->dmamap_xfer,
|
||||
(xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, ccb->dmamap_xfer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, put the results of the operation
|
||||
* into the xfer and call whoever started it
|
||||
|
@ -921,11 +1042,12 @@ bha_init(sc)
|
|||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
bus_dma_segment_t seg;
|
||||
struct bha_devices devices;
|
||||
struct bha_setup setup;
|
||||
struct bha_mailbox mailbox;
|
||||
struct bha_period period;
|
||||
int i, rlen;
|
||||
int i, rlen, rseg;
|
||||
|
||||
/* Enable round-robin scheme - appeared at firmware rev. 3.31. */
|
||||
if (strcmp(sc->sc_firmware, "3.31") >= 0) {
|
||||
|
@ -1014,6 +1136,34 @@ bha_init(sc)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the mailbox.
|
||||
*/
|
||||
if (bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1,
|
||||
&rseg, BUS_DMA_NOWAIT) ||
|
||||
bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
|
||||
(caddr_t *)&wmbx, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC))
|
||||
panic("bha_init: can't create or map mailbox");
|
||||
|
||||
/*
|
||||
* Since DMA memory allocation is always rounded up to a
|
||||
* page size, create some ccbs from the leftovers.
|
||||
*/
|
||||
if (bha_create_ccbs(sc, ((caddr_t)wmbx) +
|
||||
ALIGN(sizeof(struct bha_mbx)),
|
||||
NBPG - ALIGN(sizeof(struct bha_mbx))))
|
||||
panic("bha_init: can't create ccbs");
|
||||
|
||||
/*
|
||||
* Create and load the mailbox DMA map.
|
||||
*/
|
||||
if (bus_dmamap_create(sc->sc_dmat, sizeof(struct bha_mbx), 1,
|
||||
sizeof(struct bha_mbx), 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
|
||||
&sc->sc_dmamap_mbox) ||
|
||||
bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox, wmbx,
|
||||
sizeof(struct bha_mbx), NULL, BUS_DMA_NOWAIT))
|
||||
panic("bha_init: can't create or load mailbox dma map");
|
||||
|
||||
/*
|
||||
* Set up initial mail box for round-robin operation.
|
||||
*/
|
||||
|
@ -1028,7 +1178,7 @@ bha_init(sc)
|
|||
/* Initialize mail box. */
|
||||
mailbox.cmd.opcode = BHA_MBX_INIT_EXTENDED;
|
||||
mailbox.cmd.nmbx = BHA_MBX_SIZE;
|
||||
ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
|
||||
ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, mailbox.cmd.addr);
|
||||
bha_cmd(iot, ioh, sc,
|
||||
sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
|
||||
0, (u_char *)0);
|
||||
|
@ -1097,9 +1247,6 @@ bha_inquire_setup_information(sc)
|
|||
*p = '\0';
|
||||
} else
|
||||
strcpy(sc->sc_model, "542B");
|
||||
|
||||
printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
|
||||
sc->sc_model, sc->sc_firmware);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1107,8 +1254,8 @@ bhaminphys(bp)
|
|||
struct buf *bp;
|
||||
{
|
||||
|
||||
if (bp->b_bcount > ((BHA_NSEG - 1) << PGSHIFT))
|
||||
bp->b_bcount = ((BHA_NSEG - 1) << PGSHIFT);
|
||||
if (bp->b_bcount > BHA_MAXXFER)
|
||||
bp->b_bcount = BHA_MAXXFER;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
|
@ -1122,15 +1269,9 @@ bha_scsi_cmd(xs)
|
|||
{
|
||||
struct scsi_link *sc_link = xs->sc_link;
|
||||
struct bha_softc *sc = sc_link->adapter_softc;
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct bha_ccb *ccb;
|
||||
struct bha_scat_gath *sg;
|
||||
int seg; /* scatter gather seg being worked on */
|
||||
u_long thiskv, thisphys, nextphys;
|
||||
int bytes_this_seg, bytes_this_page, datalen, flags;
|
||||
#ifdef TFS
|
||||
struct iovec *iovp;
|
||||
#endif
|
||||
int s;
|
||||
int error, seg, flags, s;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("bha_scsi_cmd\n"));
|
||||
/*
|
||||
|
@ -1161,92 +1302,60 @@ bha_scsi_cmd(xs)
|
|||
}
|
||||
|
||||
if (xs->datalen) {
|
||||
sg = ccb->scat_gath;
|
||||
seg = 0;
|
||||
#ifdef TFS
|
||||
/*
|
||||
* Map the DMA transfer.
|
||||
*/
|
||||
#ifdef TFS
|
||||
if (flags & SCSI_DATA_UIO) {
|
||||
iovp = ((struct uio *)xs->data)->uio_iov;
|
||||
datalen = ((struct uio *)xs->data)->uio_iovcnt;
|
||||
xs->datalen = 0;
|
||||
while (datalen && seg < BHA_NSEG) {
|
||||
ltophys(iovp->iov_base, sg->seg_addr);
|
||||
ltophys(iovp->iov_len, sg->seg_len);
|
||||
xs->datalen += iovp->iov_len;
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
|
||||
iovp->iov_len, iovp->iov_base));
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
datalen--;
|
||||
}
|
||||
error = bus_dmamap_load_uio(dmat,
|
||||
ccb->dmamap_xfer, (struct uio *)xs->data,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
} else
|
||||
#endif /* TFS */
|
||||
#endif /* TFS */
|
||||
{
|
||||
/*
|
||||
* Set up the scatter-gather block.
|
||||
*/
|
||||
SC_DEBUG(sc_link, SDEV_DB4,
|
||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
||||
|
||||
datalen = xs->datalen;
|
||||
thiskv = (u_long)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
||||
while (datalen && seg < BHA_NSEG) {
|
||||
bytes_this_seg = 0;
|
||||
|
||||
/* put in the base address */
|
||||
ltophys(thisphys, sg->seg_addr);
|
||||
|
||||
SC_DEBUGN(sc_link, SDEV_DB4,
|
||||
("0x%x", thisphys));
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
while (datalen && thisphys == nextphys) {
|
||||
/*
|
||||
* This page is contiguous (physically)
|
||||
* with the the last, just extend the
|
||||
* length
|
||||
*/
|
||||
/* how far to the end of the page */
|
||||
nextphys =
|
||||
(thisphys & ~PGOFSET) + NBPG;
|
||||
bytes_this_page = nextphys - thisphys;
|
||||
/**** or the data ****/
|
||||
bytes_this_page = min(bytes_this_page,
|
||||
datalen);
|
||||
bytes_this_seg += bytes_this_page;
|
||||
datalen -= bytes_this_page;
|
||||
|
||||
/* get more ready for the next page */
|
||||
thiskv = (thiskv & ~PGOFSET) + NBPG;
|
||||
if (datalen)
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
}
|
||||
/*
|
||||
* next page isn't contiguous, finish the seg
|
||||
*/
|
||||
SC_DEBUGN(sc_link, SDEV_DB4,
|
||||
("(0x%x)", bytes_this_seg));
|
||||
ltophys(bytes_this_seg, sg->seg_len);
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
error = bus_dmamap_load(dmat,
|
||||
ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
}
|
||||
/* end of iov/kv decision */
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
|
||||
if (datalen) {
|
||||
/*
|
||||
* there's still data, must have run out of segs!
|
||||
*/
|
||||
printf("%s: bha_scsi_cmd, more than %d dma segs\n",
|
||||
sc->sc_dev.dv_xname, BHA_NSEG);
|
||||
|
||||
if (error) {
|
||||
if (error == EFBIG) {
|
||||
printf("%s: bha_scsi_cmd, more than %d"
|
||||
" dma segments\n",
|
||||
sc->sc_dev.dv_xname, BHA_NSEG);
|
||||
} else {
|
||||
printf("%s: bha_scsi_cmd, error %d loading"
|
||||
" dma map\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
|
||||
ltophys(seg * sizeof(struct bha_scat_gath), ccb->data_length);
|
||||
} else { /* No data xfer, use non S/G values */
|
||||
|
||||
bus_dmamap_sync(dmat, ccb->dmamap_xfer,
|
||||
(flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/*
|
||||
* Load the hardware scatter/gather map with the
|
||||
* contents of the DMA map.
|
||||
*/
|
||||
for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
|
||||
ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
|
||||
ccb->scat_gath[seg].seg_addr);
|
||||
ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
|
||||
ccb->scat_gath[seg].seg_len);
|
||||
}
|
||||
|
||||
ltophys(ccb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct bha_ccb, scat_gath), ccb->data_addr);
|
||||
ltophys(ccb->dmamap_xfer->dm_nsegs *
|
||||
sizeof(struct bha_scat_gath), ccb->data_length);
|
||||
} else {
|
||||
/*
|
||||
* No data xfer, use non S/G values.
|
||||
*/
|
||||
ltophys(0, ccb->data_addr);
|
||||
ltophys(0, ccb->data_length);
|
||||
}
|
||||
|
@ -1255,7 +1364,8 @@ bha_scsi_cmd(xs)
|
|||
ccb->data_in = 0;
|
||||
ccb->target = sc_link->target;
|
||||
ccb->lun = sc_link->lun;
|
||||
ltophys(KVTOPHYS(&ccb->scsi_sense), ccb->sense_ptr);
|
||||
ltophys(ccb->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct bha_ccb, scsi_sense), ccb->sense_ptr);
|
||||
ccb->req_sense_length = sizeof(ccb->scsi_sense);
|
||||
ccb->host_stat = 0x00;
|
||||
ccb->target_stat = 0x00;
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
/* $NetBSD: bhareg.h,v 1.6 1997/01/04 16:47:03 jonathan Exp $ */
|
||||
/* $NetBSD: bhareg.h,v 1.7 1997/06/06 23:31:03 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
|
||||
|
@ -199,6 +236,23 @@ struct bha_ccb {
|
|||
#define CCB_SENDING 0x04
|
||||
#endif
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* DMA maps used by the CCB. These maps are created
|
||||
* in bha_init_ccb().
|
||||
*/
|
||||
|
||||
/*
|
||||
* This DMA map maps an individual CCB. This map is
|
||||
* permanently loaded in bha_init_ccb().
|
||||
*/
|
||||
bus_dmamap_t dmamap_self;
|
||||
|
||||
/*
|
||||
* This DMA map maps the buffer involved in the transfer.
|
||||
* Its contents are loaded into "scat_gath" above.
|
||||
*/
|
||||
bus_dmamap_t dmamap_xfer;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bhavar.h,v 1.6 1997/03/28 23:47:11 mycroft Exp $ */
|
||||
/* $NetBSD: bhavar.h,v 1.7 1997/06/06 23:31:04 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
|
@ -59,10 +59,13 @@ struct bha_softc {
|
|||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
bus_dmamap_t sc_dmamap_mbox; /* maps the mailbox */
|
||||
int sc_dmaflags; /* bus-specific dma map flags */
|
||||
void *sc_ih;
|
||||
|
||||
struct bha_mbx sc_mbx; /* all our mailboxes */
|
||||
#define wmbx (&sc->sc_mbx)
|
||||
struct bha_mbx *sc_mbx; /* all our mailboxes */
|
||||
#define wmbx (sc->sc_mbx)
|
||||
struct bha_ccb *sc_ccbhash[CCB_HASH_SIZE];
|
||||
TAILQ_HEAD(, bha_ccb) sc_free_ccb, sc_waiting_ccb;
|
||||
int sc_numccbs, sc_mbofull;
|
||||
|
@ -86,3 +89,4 @@ void bha_attach __P((struct bha_softc *, struct bha_probe_data *));
|
|||
int bha_intr __P((void *));
|
||||
|
||||
int bha_disable_isacompat __P((struct bha_softc *));
|
||||
void bha_inquire_setup_information __P((struct bha_softc *));
|
||||
|
|
269
sys/dev/ic/uha.c
269
sys/dev/ic/uha.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uha.c,v 1.7 1997/03/29 02:32:31 mycroft Exp $ */
|
||||
/* $NetBSD: uha.c,v 1.8 1997/06/06 23:31:05 thorpej Exp $ */
|
||||
|
||||
#undef UHADEBUG
|
||||
#ifdef DDB
|
||||
|
@ -7,6 +7,43 @@
|
|||
#define integrate static inline
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
*
|
||||
|
@ -83,7 +120,7 @@
|
|||
#define Debugger() panic("should call debugger here (uha.c)")
|
||||
#endif /* ! DDB */
|
||||
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
#define UHA_MAXXFER ((UHA_NSEG - 1) << PGSHIFT)
|
||||
|
||||
integrate void uha_reset_mscp __P((struct uha_softc *, struct uha_mscp *));
|
||||
void uha_free_mscp __P((struct uha_softc *, struct uha_mscp *));
|
||||
|
@ -91,6 +128,7 @@ integrate void uha_init_mscp __P((struct uha_softc *, struct uha_mscp *));
|
|||
struct uha_mscp *uha_get_mscp __P((struct uha_softc *, int));
|
||||
void uhaminphys __P((struct buf *));
|
||||
int uha_scsi_cmd __P((struct scsi_xfer *));
|
||||
int uha_create_mscps __P((struct uha_softc *, void *, size_t));
|
||||
|
||||
struct scsi_adapter uha_switch = {
|
||||
uha_scsi_cmd,
|
||||
|
@ -113,6 +151,9 @@ struct cfdriver uha_cd = {
|
|||
|
||||
#define UHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
|
||||
|
||||
/* XXX Should put this in a better place. */
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find
|
||||
*/
|
||||
|
@ -122,9 +163,10 @@ uha_attach(sc, upd)
|
|||
struct uha_probe_data *upd;
|
||||
{
|
||||
|
||||
(sc->init)(sc);
|
||||
TAILQ_INIT(&sc->sc_free_mscp);
|
||||
|
||||
(sc->init)(sc);
|
||||
|
||||
/*
|
||||
* fill in the prototype scsi_link.
|
||||
*/
|
||||
|
@ -181,20 +223,94 @@ uha_init_mscp(sc, mscp)
|
|||
struct uha_softc *sc;
|
||||
struct uha_mscp *mscp;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
int hashnum;
|
||||
|
||||
/*
|
||||
* XXX Should we put a DIAGNOSTIC check for multiple
|
||||
* XXX MSCP inits here?
|
||||
*/
|
||||
|
||||
bzero(mscp, sizeof(struct uha_mscp));
|
||||
|
||||
/*
|
||||
* Create the DMA maps for this MSCP.
|
||||
*/
|
||||
if (bus_dmamap_create(dmat, sizeof(struct uha_mscp), 1,
|
||||
sizeof(struct uha_mscp), 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
|
||||
&mscp->dmamap_self) ||
|
||||
|
||||
/* XXX What's a good value for this? */
|
||||
bus_dmamap_create(dmat, UHA_MAXXFER, UHA_NSEG, UHA_MAXXFER,
|
||||
0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
|
||||
&mscp->dmamap_xfer))
|
||||
panic("uha_init_mscp: can't create DMA maps");
|
||||
|
||||
/*
|
||||
* Load the permanent DMA maps.
|
||||
*/
|
||||
if (bus_dmamap_load(dmat, mscp->dmamap_self, mscp,
|
||||
sizeof(struct uha_mscp), NULL, BUS_DMA_NOWAIT))
|
||||
panic("uha_init_mscp: can't load permanent maps");
|
||||
|
||||
/*
|
||||
* put in the phystokv hash table
|
||||
* Never gets taken out.
|
||||
*/
|
||||
mscp->hashkey = KVTOPHYS(mscp);
|
||||
mscp->hashkey = mscp->dmamap_self->dm_segs[0].ds_addr;
|
||||
hashnum = MSCP_HASH(mscp->hashkey);
|
||||
mscp->nexthash = sc->sc_mscphash[hashnum];
|
||||
sc->sc_mscphash[hashnum] = mscp;
|
||||
uha_reset_mscp(sc, mscp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a set of MSCPs and add them to the free list.
|
||||
*/
|
||||
int
|
||||
uha_create_mscps(sc, mem, size)
|
||||
struct uha_softc *sc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
{
|
||||
bus_dma_segment_t seg;
|
||||
struct uha_mscp *mscp;
|
||||
int rseg, error;
|
||||
|
||||
if (sc->sc_nummscps >= UHA_MSCP_MAX)
|
||||
return (0);
|
||||
|
||||
if ((mscp = mem) != NULL)
|
||||
goto have_mem;
|
||||
|
||||
size = NBPG;
|
||||
error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
|
||||
(caddr_t *)&mscp, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
|
||||
if (error) {
|
||||
bus_dmamem_free(sc->sc_dmat, &seg, rseg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
have_mem:
|
||||
bzero(mscp, size);
|
||||
while (size > sizeof(struct uha_mscp)) {
|
||||
uha_init_mscp(sc, mscp);
|
||||
sc->sc_nummscps++;
|
||||
TAILQ_INSERT_TAIL(&sc->sc_free_mscp, mscp, chain);
|
||||
(caddr_t)mscp += ALIGN(sizeof(struct uha_mscp));
|
||||
size -= ALIGN(sizeof(struct uha_mscp));
|
||||
if (sc->sc_nummscps >= UHA_MSCP_MAX)
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a free mscp
|
||||
*
|
||||
|
@ -222,16 +338,12 @@ uha_get_mscp(sc, flags)
|
|||
break;
|
||||
}
|
||||
if (sc->sc_nummscps < UHA_MSCP_MAX) {
|
||||
mscp = (struct uha_mscp *) malloc(sizeof(struct uha_mscp),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (!mscp) {
|
||||
printf("%s: can't malloc mscp\n",
|
||||
if (uha_create_mscps(sc, NULL, 0)) {
|
||||
printf("%s: can't allocate mscps\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto out;
|
||||
}
|
||||
uha_init_mscp(sc, mscp);
|
||||
sc->sc_nummscps++;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if ((flags & SCSI_NOSLEEP) != 0)
|
||||
goto out;
|
||||
|
@ -273,10 +385,23 @@ uha_done(sc, mscp)
|
|||
struct uha_softc *sc;
|
||||
struct uha_mscp *mscp;
|
||||
{
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct scsi_sense_data *s1, *s2;
|
||||
struct scsi_xfer *xs = mscp->xs;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
|
||||
|
||||
/*
|
||||
* If we were a data transfer, unload the map that described
|
||||
* the data buffer.
|
||||
*/
|
||||
if (xs->datalen) {
|
||||
bus_dmamap_sync(dmat, mscp->dmamap_xfer,
|
||||
(xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, mscp->dmamap_xfer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, put the results of the operation
|
||||
* into the xfer and call whoever started it
|
||||
|
@ -326,8 +451,8 @@ uhaminphys(bp)
|
|||
struct buf *bp;
|
||||
{
|
||||
|
||||
if (bp->b_bcount > ((UHA_NSEG - 1) << PGSHIFT))
|
||||
bp->b_bcount = ((UHA_NSEG - 1) << PGSHIFT);
|
||||
if (bp->b_bcount > UHA_MAXXFER)
|
||||
bp->b_bcount = UHA_MAXXFER;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
|
@ -341,12 +466,10 @@ uha_scsi_cmd(xs)
|
|||
{
|
||||
struct scsi_link *sc_link = xs->sc_link;
|
||||
struct uha_softc *sc = sc_link->adapter_softc;
|
||||
bus_dma_tag_t dmat = sc->sc_dmat;
|
||||
struct uha_mscp *mscp;
|
||||
struct uha_dma_seg *sg;
|
||||
int seg; /* scatter gather seg being worked on */
|
||||
u_long thiskv, thisphys, nextphys;
|
||||
int bytes_this_seg, bytes_this_page, datalen, flags;
|
||||
int s;
|
||||
int error, seg, flags, s;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
|
||||
/*
|
||||
|
@ -380,7 +503,8 @@ uha_scsi_cmd(xs)
|
|||
mscp->target = sc_link->target;
|
||||
mscp->lun = sc_link->lun;
|
||||
mscp->scsi_cmd_length = xs->cmdlen;
|
||||
mscp->sense_ptr = KVTOPHYS(&mscp->mscp_sense);
|
||||
mscp->sense_ptr = mscp->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct uha_mscp, mscp_sense);
|
||||
mscp->req_sense_length = sizeof(mscp->mscp_sense);
|
||||
mscp->host_stat = 0x00;
|
||||
mscp->target_stat = 0x00;
|
||||
|
@ -390,84 +514,49 @@ uha_scsi_cmd(xs)
|
|||
seg = 0;
|
||||
#ifdef TFS
|
||||
if (flags & SCSI_DATA_UIO) {
|
||||
struct iovec *iovp;
|
||||
iovp = ((struct uio *) xs->data)->uio_iov;
|
||||
datalen = ((struct uio *) xs->data)->uio_iovcnt;
|
||||
xs->datalen = 0;
|
||||
while (datalen && seg < UHA_NSEG) {
|
||||
sg->seg_addr = (physaddr)iovp->iov_base;
|
||||
sg->seg_len = iovp->iov_len;
|
||||
xs->datalen += iovp->iov_len;
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
|
||||
iovp->iov_len, iovp->iov_base));
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
datalen--;
|
||||
}
|
||||
error = bus_dmamap_load_uio(dmat,
|
||||
mscp->dmamap_xfer, (struct uio *)xs->data,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
} else
|
||||
#endif /*TFS */
|
||||
{
|
||||
/*
|
||||
* Set up the scatter gather block
|
||||
*/
|
||||
SC_DEBUG(sc_link, SDEV_DB4,
|
||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int) xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
||||
while (datalen && seg < UHA_NSEG) {
|
||||
bytes_this_seg = 0;
|
||||
|
||||
/* put in the base address */
|
||||
sg->seg_addr = thisphys;
|
||||
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
while (datalen && thisphys == nextphys) {
|
||||
/*
|
||||
* This page is contiguous (physically)
|
||||
* with the the last, just extend the
|
||||
* length
|
||||
*/
|
||||
/* how far to the end of the page */
|
||||
nextphys = (thisphys & ~PGOFSET) + NBPG;
|
||||
bytes_this_page = nextphys - thisphys;
|
||||
/**** or the data ****/
|
||||
bytes_this_page = min(bytes_this_page,
|
||||
datalen);
|
||||
bytes_this_seg += bytes_this_page;
|
||||
datalen -= bytes_this_page;
|
||||
|
||||
/* get more ready for the next page */
|
||||
thiskv = (thiskv & ~PGOFSET) + NBPG;
|
||||
if (datalen)
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
}
|
||||
/*
|
||||
* next page isn't contiguous, finish the seg
|
||||
*/
|
||||
SC_DEBUGN(sc_link, SDEV_DB4,
|
||||
("(0x%x)", bytes_this_seg));
|
||||
sg->seg_len = bytes_this_seg;
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
error = bus_dmamap_load(dmat,
|
||||
mscp->dmamap_xfer, xs->data, xs->datalen, NULL,
|
||||
(flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
|
||||
BUS_DMA_WAITOK);
|
||||
}
|
||||
/* end of iov/kv decision */
|
||||
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
|
||||
if (datalen) {
|
||||
/*
|
||||
* there's still data, must have run out of segs!
|
||||
*/
|
||||
printf("%s: uha_scsi_cmd, more than %d dma segs\n",
|
||||
sc->sc_dev.dv_xname, UHA_NSEG);
|
||||
|
||||
if (error) {
|
||||
if (error == EFBIG) {
|
||||
printf("%s: uha_scsi_cmd, more than %d"
|
||||
" dma segments\n",
|
||||
sc->sc_dev.dv_xname, UHA_NSEG);
|
||||
} else {
|
||||
printf("%s: uha_scsi_cmd, error %d loading"
|
||||
" dma map\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
mscp->data_addr = KVTOPHYS(mscp->uha_dma);
|
||||
|
||||
bus_dmamap_sync(dmat, mscp->dmamap_xfer,
|
||||
(flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/*
|
||||
* Load the hardware scatter/gather map with the
|
||||
* contents of the DMA map.
|
||||
*/
|
||||
for (seg = 0; seg < mscp->dmamap_xfer->dm_nsegs; seg++) {
|
||||
mscp->uha_dma[seg].seg_addr =
|
||||
mscp->dmamap_xfer->dm_segs[seg].ds_addr;
|
||||
mscp->uha_dma[seg].seg_len =
|
||||
mscp->dmamap_xfer->dm_segs[seg].ds_len;
|
||||
}
|
||||
|
||||
mscp->data_addr = mscp->dmamap_self->dm_segs[0].ds_addr +
|
||||
offsetof(struct uha_mscp, uha_dma);
|
||||
mscp->data_length = xs->datalen;
|
||||
mscp->sgth = 0x01;
|
||||
mscp->sg_num = seg;
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
/* $NetBSD: uhareg.h,v 1.2 1996/09/01 00:54:41 mycroft Exp $ */
|
||||
/* $NetBSD: uhareg.h,v 1.3 1997/06/06 23:31:06 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
|
||||
|
@ -226,6 +263,24 @@ struct uha_mscp {
|
|||
#define MSCP_ALLOC 0x01
|
||||
#define MSCP_ABORT 0x02
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* DMA maps used by the MSCP. These maps are created
|
||||
* in uha_init_mscp().
|
||||
*/
|
||||
|
||||
/*
|
||||
* This DMA map maps an individual MSCP. This map is
|
||||
* permanently loaded in uha_init_mscp().
|
||||
*/
|
||||
bus_dmamap_t dmamap_self;
|
||||
|
||||
/*
|
||||
* This DMA map maps the buffer involved in the transfer.
|
||||
* It's contents are loaded into "uha_dma" above.
|
||||
*/
|
||||
bus_dmamap_t dmamap_xfer;
|
||||
|
||||
};
|
||||
#pragma pack(4)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uhavar.h,v 1.4 1997/03/29 02:32:32 mycroft Exp $ */
|
||||
/* $NetBSD: uhavar.h,v 1.5 1997/06/06 23:31:07 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
|
||||
|
@ -39,8 +39,11 @@ struct uha_softc {
|
|||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
void *sc_ih;
|
||||
|
||||
int sc_dmaflags; /* bus-specific DMA map creation flags */
|
||||
|
||||
void (*start_mbox) __P((struct uha_softc *, struct uha_mscp *));
|
||||
int (*poll) __P((struct uha_softc *, struct scsi_xfer *, int));
|
||||
void (*init) __P((struct uha_softc *));
|
||||
|
|
Loading…
Reference in New Issue