diff --git a/sys/dev/eisa/ahc_eisa.c b/sys/dev/eisa/ahc_eisa.c index dc849209d521..b5b1ebee3dc4 100644 --- a/sys/dev/eisa/ahc_eisa.c +++ b/sys/dev/eisa/ahc_eisa.c @@ -1,4 +1,4 @@ -/* $NetBSD: ahc_eisa.c,v 1.13 1997/08/27 11:24:42 bouyer Exp $ */ +/* $NetBSD: ahc_eisa.c,v 1.14 1998/03/16 15:40:51 leo Exp $ */ /* * Product specific probe and attach routines for: @@ -384,7 +384,7 @@ ahc_eisa_attach(parent, self, aux) } printf(": %s\n", model); - ahc_construct(ahc, iot, ioh, type, AHC_FNONE); + ahc_construct(ahc, iot, ioh, ea->eba_dmat, type, AHC_FNONE); if (eisa_intr_map(ec, irq, &ih)) { printf("%s: couldn't map interrupt (%d)\n", ahc->sc_dev.dv_xname, irq); diff --git a/sys/dev/ic/aic7xxx.c b/sys/dev/ic/aic7xxx.c index ad1867d259a9..9199ade54264 100644 --- a/sys/dev/ic/aic7xxx.c +++ b/sys/dev/ic/aic7xxx.c @@ -1,4 +1,4 @@ -/* $NetBSD: aic7xxx.c,v 1.27 1998/01/12 09:23:13 thorpej Exp $ */ +/* $NetBSD: aic7xxx.c,v 1.28 1998/03/16 15:36:17 leo Exp $ */ /* * Generic driver for the aic7xxx based adaptec SCSI controllers @@ -173,8 +173,15 @@ extern vm_offset_t alpha_XXX_dmamap(vm_offset_t); #endif /* defined(__NetBSD__) */ #include + +#define SCB_DMA_OFFSET(ahc, scb, member) \ + ((ahc)->sc_dmamap_control->dm_segs[0].ds_addr + \ + (scb)->tag * sizeof(struct scb) + \ + offsetof(struct scb, member)) #define KVTOPHYS(x) vtophys(x) +#define AHC_MAXXFER ((AHC_NSEG - 1) << PGSHIFT) + #define MIN(a,b) ((a < b) ? a : b) #define ALL_TARGETS -1 @@ -308,6 +315,8 @@ static void ahc_handle_seqint __P((struct ahc_data *ahc, u_int8_t intstat)); static struct scb * ahc_get_scb __P((struct ahc_data *ahc, int flags)); static void ahc_loadseq __P((struct ahc_data *ahc)); +static struct scb * + ahc_new_scb __P((struct ahc_data *ahc, struct scb *scb)); static int ahc_match_scb __P((struct scb *scb, int target, char channel)); static int ahc_poll __P((struct ahc_data *ahc, int wait)); #ifdef AHC_DEBUG @@ -432,10 +441,11 @@ ahc_alloc(unit, iobase, type, flags) u_long iobase; #elif defined(__NetBSD__) void -ahc_construct(ahc, st, sh, type, flags) +ahc_construct(ahc, st, sh, dt, type, flags) struct ahc_data *ahc; bus_space_tag_t st; bus_space_handle_t sh; + bus_dma_tag_t dt; #endif ahc_type type; ahc_flag flags; @@ -471,6 +481,7 @@ ahc_construct(ahc, st, sh, type, flags) #elif defined(__NetBSD__) ahc->sc_st = st; ahc->sc_sh = sh; + ahc->sc_dt = dt; #endif ahc->type = type; ahc->flags = flags; @@ -756,6 +767,7 @@ ahc_send_scb(ahc, scb) struct scb *scb; { AHC_OUTB(ahc, SCBCNT, SCBAUTO); + if( ahc->type == AHC_284 ) /* Can only do 8bit PIO */ AHC_OUTSB(ahc, SCBARRAY, scb, SCB_PIO_TRANSFER_SIZE); @@ -1652,20 +1664,36 @@ ahc_handle_seqint(ahc, intstat) sc->byte2 = xs->sc_link->AIC_SCSI_LUN << 5; sc->length = sizeof(struct scsipi_sense_data); sc->control = 0; +#if defined(__NetBSD__) + sg->addr = + SCB_DMA_OFFSET(ahc, scb, scsi_sense); +#elif defined(__FreeBSD__) sg->addr = KVTOPHYS(&xs->AIC_SCSI_SENSE); +#endif sg->len = sizeof(struct scsipi_sense_data); scb->control &= DISCENB; scb->status = 0; scb->SG_segment_count = 1; + +#if defined(__NetBSD__) + scb->SG_list_pointer = + SCB_DMA_OFFSET(ahc, scb, ahc_dma); +#elif defined(__FreeBSD__) scb->SG_list_pointer = KVTOPHYS(sg); +#endif scb->data = sg->addr; scb->datalen = sg->len; #ifdef AHC_BROKEN_CACHE if (ahc_broken_cache) INVALIDATE_CACHE(); #endif +#if defined(__NetBSD__) + scb->cmdpointer = + SCB_DMA_OFFSET(ahc, scb, sense_cmd); +#elif defined(__FreeBSD__) scb->cmdpointer = KVTOPHYS(sc); +#endif scb->cmdlen = sizeof(*sc); scb->flags |= SCB_SENSE; @@ -1751,11 +1779,16 @@ ahc_handle_seqint(ahc, intstat) */ resid_sgs = AHC_INB(ahc, SCB_RESID_SGCNT) - 1; while (resid_sgs > 0) { - int sg; + int sg; - sg = scb->SG_segment_count - resid_sgs; - xs->resid += scb->ahc_dma[sg].len; - resid_sgs--; + sg = scb->SG_segment_count - resid_sgs; +#if defined(__NetBSD_) + /* 'ahc_dma' might contain swapped values */ + xs->resid += scb->dmamap_xfer->dm_segs[sg].ds_len; +#else + xs->resid += scb->ahc_dma[sg].len; +#endif + resid_sgs--; } #if defined(__FreeBSD__) @@ -1948,6 +1981,27 @@ ahc_done(ahc, scb) struct scsipi_xfer *xs = scb->xs; SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_done\n")); + +#if defined(__NetBSD__) + /* + * If we were a data transfer, unload the map that described + * the data buffer. + */ + if (xs->datalen) { + bus_dmamap_sync(ahc->sc_dt, scb->dmamap_xfer, 0, + scb->dmamap_xfer->dm_mapsize, + (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ahc->sc_dt, scb->dmamap_xfer); + } + /* + * Sync the scb map, so all it's contents are valid + */ + bus_dmamap_sync(ahc->sc_dt, ahc->sc_dmamap_control, + (scb)->tag * sizeof(struct scb), sizeof(struct scb), + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + +#endif /* * Put the results of the operation * into the xfer and call whoever started it @@ -1959,8 +2013,13 @@ ahc_done(ahc, scb) xs->error = XS_DRIVER_STUFFUP; } else #endif - if(scb->flags & SCB_SENSE) + if(scb->flags & SCB_SENSE) { xs->error = XS_SENSE; +#if defined(__NetBSD__) + bcopy(&scb->scsi_sense, &xs->AIC_SCSI_SENSE, + sizeof(scb->scsi_sense)); +#endif + } if(scb->flags & SCB_SENTORDEREDTAG) ahc->in_timeout = FALSE; #if defined(__FreeBSD__) @@ -2038,6 +2097,12 @@ ahc_init(ahc) u_int8_t scsi_conf, sblkctl, i; u_int16_t ultraenable = 0; int max_targ = 15; +#if defined(__NetBSD__) + bus_dma_segment_t seg; + int error, rseg, scb_size; + struct scb *scb_space; +#endif + /* * Assume we have a board at this stage and it has been reset. */ @@ -2119,7 +2184,45 @@ ahc_init(ahc) ahc->maxscbs = ahc->maxhscbs; ahc->flags &= ~AHC_PAGESCBS; } - +#if defined(__NetBSD__) + /* + * We allocate the space for all control-blocks at once in + * dma-able memory. + */ + scb_size = ahc->maxscbs * sizeof(struct scb); + if ((error = bus_dmamem_alloc(ahc->sc_dt, scb_size, + NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { + printf("%s: unable to allocate control structures, " + "error = %d\n", ahc_name(ahc), error); + return -1; + } + if ((error = bus_dmamem_map(ahc->sc_dt, &seg, rseg, scb_size, + (caddr_t *)&scb_space, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf("%s: unable to map control structures, error = %d\n", + ahc_name(ahc), error); + return -1; + } + if ((error = bus_dmamap_create(ahc->sc_dt, scb_size, 1, scb_size, + 0, BUS_DMA_NOWAIT | ahc->sc_dmaflags, + &ahc->sc_dmamap_control)) != 0) { + printf("%s: unable to create control DMA map, error = %d\n", + ahc_name(ahc), error); + return -1; + } + if ((error = bus_dmamap_load(ahc->sc_dt, ahc->sc_dmamap_control, + scb_space, scb_size, NULL, BUS_DMA_NOWAIT)) != 0) { + printf("%s: unable to load control DMA map, error = %d\n", + ahc_name(ahc), error); + return -1; + } + for (i = 0; i < ahc->maxscbs; i++) { + if (ahc_new_scb(ahc, &scb_space[i]) == NULL) + break; + STAILQ_INSERT_HEAD(&ahc->page_scbs, &scb_space[i], links); + } + ahc->maxscbs = i; +#endif printf("%d SCBs\n", ahc->maxhscbs); #ifdef AHC_DEBUG @@ -2426,14 +2529,18 @@ ahc_scsi_cmd(xs) struct scb *scb; struct ahc_dma_seg *sg; int seg; /* scatter gather seg being worked on */ +#if defined(__FreeBSD__) unsigned long thiskv, nextkv; physaddr thisphys, nextphys; int bytes_this_seg, bytes_this_page, datalen, flags; +#endif + int flags; struct ahc_data *ahc; u_short mask; int s; #if defined(__NetBSD__) /* XXX */ int dontqueue = 0, fromqueue = 0; + int error; #endif ahc = (struct ahc_data *)xs->sc_link->adapter_softc; @@ -2575,18 +2682,61 @@ ahc_scsi_cmd(xs) #endif (xs->sc_link->AIC_SCSI_LUN & 0x07); scb->cmdlen = xs->cmdlen; +#if defined(__NetBSD__) + bcopy(xs->cmd, &scb->scsi_cmd, xs->cmdlen); + scb->cmdpointer = SCB_DMA_OFFSET(ahc, scb, scsi_cmd); +#elif defined(__FreeBSD__) scb->cmdpointer = KVTOPHYS(xs->cmd); +#endif xs->resid = 0; xs->status = 0; if (xs->datalen) { /* should use S/G only if not zero length */ + SC_DEBUG(xs->sc_link, SDEV_DB4, + ("%ld @%p:- ", (long)xs->datalen, xs->data)); + +#if defined(__NetBSD__) + error = bus_dmamap_load(ahc->sc_dt, scb->dmamap_xfer, + xs->data, xs->datalen, NULL, + (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : + BUS_DMA_WAITOK); + if (error) { + if (error == EFBIG) { + printf("%s: ahc_scsi_cmd: more than %d DMA segs\n", + ahc_name(ahc), AHC_NSEG); + } else { + printf("%s: ahc_scsi_cmd: error %d loading dma " + "map\n", ahc_name(ahc), error); + } + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n")); + xs->error = XS_DRIVER_STUFFUP; + ahc_free_scb(ahc, scb, flags); + return (COMPLETE); + } + bus_dmamap_sync(ahc->sc_dt, scb->dmamap_xfer, 0, + scb->dmamap_xfer->dm_mapsize, (flags & SCSI_DATA_IN) ? + BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + /* + * Load the hardware scatter/gather map with the contents + * of the DMA map. + */ + scb->SG_list_pointer = SCB_DMA_OFFSET(ahc, scb, ahc_dma); + + sg = scb->ahc_dma; + for (seg = 0; seg < scb->dmamap_xfer->dm_nsegs; seg++) { + sg->addr = scb->dmamap_xfer->dm_segs[seg].ds_addr; + sg->len = scb->dmamap_xfer->dm_segs[seg].ds_len; + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%lx", + (u_long)sg->addr)); + sg++; + } + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n")); +#elif defined(__FreeBSD__) scb->SG_list_pointer = KVTOPHYS(scb->ahc_dma); sg = scb->ahc_dma; seg = 0; /* * Set up the scatter gather block */ - SC_DEBUG(xs->sc_link, SDEV_DB4, - ("%ld @%p:- ", (long)xs->datalen, xs->data)); datalen = xs->datalen; thiskv = (unsigned long) xs->data; thisphys = KVTOPHYS(thiskv); @@ -2633,11 +2783,6 @@ ahc_scsi_cmd(xs) sg++; seg++; } - scb->SG_segment_count = seg; - - /* Copy the first SG into the data pointer area */ - scb->data = scb->ahc_dma->addr; - scb->datalen = scb->ahc_dma->len; SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n")); if (datalen) { /* there's still data, must have run out of segs! */ @@ -2647,6 +2792,12 @@ ahc_scsi_cmd(xs) ahc_free_scb(ahc, scb, flags); return (COMPLETE); } +#endif + scb->SG_segment_count = seg; + + /* Copy the first SG into the data pointer area */ + scb->data = scb->ahc_dma->addr; + scb->datalen = scb->ahc_dma->len; #ifdef AHC_BROKEN_CACHE if (ahc_broken_cache) INVALIDATE_CACHE(); @@ -2661,6 +2812,11 @@ ahc_scsi_cmd(xs) scb->data = 0; scb->datalen = 0; } +#if defined(__NetBSD__) + bus_dmamap_sync(ahc->sc_dt, ahc->sc_dmamap_control, + (scb)->tag * sizeof(struct scb), sizeof(struct scb), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); +#endif #ifdef AHC_DEBUG if((ahc_debug & AHC_SHOWSCBS) && @@ -2785,6 +2941,53 @@ ahc_free_scb(ahc, scb, flags) splx(opri); } +/* + * Allocate and initialize a new scb + */ +static struct scb * +ahc_new_scb(ahc, scbp) + struct ahc_data *ahc; + struct scb *scbp; +{ +#if defined(__NetBSD__) + int error; +#endif + + if (scbp == NULL) + scbp = (struct scb *) malloc(sizeof(struct scb), M_TEMP, M_NOWAIT); + + if (scbp != NULL) { + bzero(scbp, sizeof(struct scb)); +#if defined(__NetBSD__) + error = bus_dmamap_create(ahc->sc_dt, AHC_MAXXFER, AHC_NSEG, + AHC_MAXXFER, 0, + BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW|ahc->sc_dmaflags, + &scbp->dmamap_xfer); + if (error) { + printf("%s: unable to create DMA map, error = %d\n", + ahc_name(ahc), error); + free(scbp, M_TEMP); + return (NULL); + } +#endif + scbp->tag = ahc->numscbs; + if( ahc->numscbs < ahc->maxhscbs ) + scbp->position = ahc->numscbs; + else + scbp->position = SCB_LIST_NULL; + ahc->numscbs++; + /* + * Place in the scbarray + * Never is removed. + */ + ahc->scbarray[scbp->tag] = scbp; + } + else { + printf("%s: Can't malloc SCB\n", ahc_name(ahc)); + } + return (scbp); +} + /* * Get a free scb, either one already assigned to a hardware slot * on the adapter or one that will require an SCB to be paged out before @@ -2811,28 +3014,11 @@ ahc_get_scb(ahc, flags) else if((scbp = ahc->page_scbs.stqh_first)) { STAILQ_REMOVE_HEAD(&ahc->page_scbs, links); } +#if defined(__FreeBSD__) else if(ahc->numscbs < ahc->maxscbs) { - scbp = (struct scb *) malloc(sizeof(struct scb), - M_TEMP, M_NOWAIT); - if (scbp) { - bzero(scbp, sizeof(struct scb)); - scbp->tag = ahc->numscbs; - if( ahc->numscbs < ahc->maxhscbs ) - scbp->position = ahc->numscbs; - else - scbp->position = SCB_LIST_NULL; - ahc->numscbs++; - /* - * Place in the scbarray - * Never is removed. - */ - ahc->scbarray[scbp->tag] = scbp; - } - else { - printf("%s: Can't malloc SCB\n", - ahc_name(ahc)); - } + scbp = ahc_new_scb(ahc); } +#endif else { if (!(flags & SCSI_NOSLEEP)) { tsleep((caddr_t)&ahc->free_scbs, PRIBIO, diff --git a/sys/dev/ic/aic7xxxvar.h b/sys/dev/ic/aic7xxxvar.h index 5dc3eb3862cc..e2ea4ad7cdc4 100644 --- a/sys/dev/ic/aic7xxxvar.h +++ b/sys/dev/ic/aic7xxxvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: aic7xxxvar.h,v 1.14 1997/08/27 11:24:50 bouyer Exp $ */ +/* $NetBSD: aic7xxxvar.h,v 1.15 1998/03/16 15:36:17 leo Exp $ */ /* * Interface to the generic driver for the aic7xxx based adaptec @@ -203,6 +203,17 @@ struct scb { u_char position; /* Position in card's scbarray */ struct ahc_dma_seg ahc_dma[AHC_NSEG]; struct scsipi_sense sense_cmd; /* SCSI command block */ + +#if defined(__NetBSD__) + /* + * This DMA map maps the buffer involved in the transfer. + * Its contents are loaded into "ahc_dma" above. + */ + bus_dmamap_t dmamap_xfer; + + struct scsi_generic scsi_cmd; /* dma-able copy of xs->cmd */ + struct scsipi_sense_data scsi_sense; +#endif }; struct ahc_data { @@ -213,6 +224,10 @@ struct ahc_data { void *sc_ih; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; + bus_dma_tag_t sc_dt; + int sc_dmaflags; + + bus_dmamap_t sc_dmamap_control; /* Maps the control blocks */ LIST_HEAD(, scsipi_xfer) sc_xxxq; /* XXX software request queue */ struct scsipi_xfer *sc_xxxqlast; /* last entry in queue */ #endif @@ -300,7 +315,8 @@ struct ahc_data *ahc_alloc __P((int unit, u_long io_base, ahc_type type, ahc_fla void ahc_reset __P((char *devname, bus_space_tag_t st, bus_space_handle_t sh)); void ahc_construct __P((struct ahc_data *ahc, bus_space_tag_t st, - bus_space_handle_t sh, ahc_type type, ahc_flag flags)); + bus_space_handle_t sh, bus_dma_tag_t dt, ahc_type type, + ahc_flag flags)); #endif void ahc_free __P((struct ahc_data *)); int ahc_init __P((struct ahc_data *)); diff --git a/sys/dev/pci/ahc_pci.c b/sys/dev/pci/ahc_pci.c index 31670fceaf6e..64ab13156dac 100644 --- a/sys/dev/pci/ahc_pci.c +++ b/sys/dev/pci/ahc_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ahc_pci.c,v 1.16 1997/08/27 11:25:20 bouyer Exp $ */ +/* $NetBSD: ahc_pci.c,v 1.17 1998/03/16 15:39:13 leo Exp $ */ /* * Product specific probe and attach routines for: @@ -475,7 +475,7 @@ ahc_pci_attach(parent, self, aux) return; } #elif defined(__NetBSD__) - ahc_construct(ahc, st, sh, ahc_t, ahc_f); + ahc_construct(ahc, st, sh, pa->pa_dmat, ahc_t, ahc_f); if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, &ih)) {