Subject: cleanup jazzio bus_dma
To: None <port-arc@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-arc
Date: 01/19/2003 20:16:56
Hi,

I've made another patch to cleanup jazzio DMA code and
nuke functions in old arc/jazz/dma.c.

Currently jazzio/fdc_jazzio.c and jazzio/asc.c still use
DMA functions in jazz/dma.[ch] and they haven't switched to
bus_dma(9) on jazzio because jazz/bus_dma_jazzio.c
cannot provide contiguous jazzio VA space for linear buffer
on CPU VA space that picaDma*() functions in dma.c do.

To fix this, I change jazz_bus_dmamap_create() to allocate
jazz dmatlb if BUS_DMA_ALLOCNOW flag is specified and
nsegment is 1. In that case, jazz_bus_dmamap_load() just
call jazz_dmatlb_map_va() to map CPU VA space into jazzio
VA space with pre-allocated TLB entries (like dma.c does).
bus_dmamap_load_{mbuf,uio,raw} functions are not allowed
if dmamap is created with BUS_DMA_ALLOCNOW flag.
(i.e. ALLOCNOW is valid only for linear buffers.)

DMAC regsters are handled by each driver to start/stop DMA.
In fdc_jazzio.c, DMAC bus_space is also mapped in the attachment,
and DMAC commands are sent in fdc_jazzio_dma_start() and
fdc_jazzio_dma_done().

I also rewrite (or just cut-and-paste ;-) asc.c that uses
MI ncr53c9x SCSI driver. DMAC operations in it is mostly
same with fdc_jazzio.c and glue functions for it are
also similar with other ncr53c9x based drivers, but this
is completely untested (I don't have Magnum or Pica machines).

These changes are based on discussion in port-arc/13388,
but further comments/suggestions are appreciated.
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp


(Note: please remove jazz/asc.c before applying the attached patch.
 Actuall diff against current asc.c is too large..)

Index: jazz/bus_dma_jazz.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/bus_dma_jazz.c,v
retrieving revision 1.4
diff -u -r1.4 bus_dma_jazz.c
--- jazz/bus_dma_jazz.c	2001/11/14 18:15:15	1.4
+++ jazz/bus_dma_jazz.c	2003/01/19 10:06:51
@@ -39,11 +39,19 @@
 #include <arc/jazz/jazzdmatlbreg.h>
 #include <arc/jazz/jazzdmatlbvar.h>
 
+typedef struct jazz_tlbmap {
+	struct jazz_dma_pte *ptebase;
+	bus_addr_t vaddr;
+} *jazz_tlbmap_t;
+
 static int	jazz_bus_dmamap_alloc_sgmap __P((bus_dma_tag_t,
 		    bus_dma_segment_t *, int, bus_size_t, struct proc *, int));
 static void	jazz_bus_dmamap_free_sgmap __P((bus_dma_tag_t,
 		    bus_dma_segment_t *, int));
 
+int	jazz_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int,
+	    bus_size_t, bus_size_t, int, bus_dmamap_t *));
+void	jazz_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
 int	jazz_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
 	    bus_size_t, struct proc *, int));
 int	jazz_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
@@ -62,6 +70,8 @@
 {
 	_bus_dma_tag_init(t);
 
+	t->_dmamap_create = jazz_bus_dmamap_create;
+	t->_dmamap_destroy = jazz_bus_dmamap_destroy;
 	t->_dmamap_load = jazz_bus_dmamap_load;
 	t->_dmamap_load_mbuf = jazz_bus_dmamap_load_mbuf;
 	t->_dmamap_load_uio = jazz_bus_dmamap_load_uio;
@@ -117,6 +127,83 @@
 	}
 }
 
+
+/*
+ * function to create a DMA map. If BUS_DMA_ALLOCNOW is specified and
+ * nsegments is 1, allocate jazzdmatlb here, too.
+ */
+int
+jazz_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
+	bus_dma_tag_t t;
+	bus_size_t size;
+	int nsegments;
+	bus_size_t maxsegsz;
+	bus_size_t boundary;
+	int flags;
+	bus_dmamap_t *dmamp;
+{
+	struct arc_bus_dmamap *map;
+	jazz_tlbmap_t tlbmap;
+	int error, npte;
+
+	if ((flags & BUS_DMA_ALLOCNOW) == 0)
+		return (_bus_dmamap_create(t, size, nsegments, maxsegsz,
+		    boundary, flags, dmamp));
+
+	if (nsegments > 1)
+		/* BUS_DMA_ALLOCNOW is allowd only with one segment for now. */
+		return (ENOMEM);
+
+	tlbmap = malloc(sizeof(struct jazz_tlbmap), M_DMAMAP,
+	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK);
+	if (tlbmap == NULL)
+		return (ENOMEM);
+
+	npte = jazz_dma_page_round(maxsegsz) / JAZZ_DMA_PAGE_SIZE + 1;
+	tlbmap->ptebase =
+	    jazz_dmatlb_alloc(npte, boundary, flags, &tlbmap->vaddr);
+	if (tlbmap->ptebase == NULL) {
+		free(tlbmap, M_DMAMAP);
+		return (ENOMEM);
+	}
+
+	error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
+	    flags, dmamp);
+	if (error != 0) {
+		jazz_dmatlb_free(tlbmap->vaddr, npte);
+		free(tlbmap, M_DMAMAP);
+		return (error);
+	}
+	map = *dmamp;
+	map->_dm_cookie = (void *)tlbmap;
+
+	return (0);
+}
+
+/*
+ * function to destroy a DMA map. If BUS_DMA_ALLOCNOW is specified,
+ * free jazzdmatlb, too.
+ */
+void
+jazz_bus_dmamap_destroy(t, map)
+	bus_dma_tag_t t;
+	bus_dmamap_t map;
+{
+
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0) {
+		jazz_tlbmap_t tlbmap;
+		int npte;
+
+		tlbmap = (jazz_tlbmap_t)map->_dm_cookie;
+		npte = jazz_dma_page_round(map->_dm_maxsegsz) /
+		    JAZZ_DMA_PAGE_SIZE + 1;
+		jazz_dmatlb_free(tlbmap->vaddr, npte);
+		free(tlbmap, M_DMAMAP);
+	}
+
+	_bus_dmamap_destroy(t, map);
+}
+
 /*
  * function for loading a direct-mapped DMA map with a linear buffer.
  */
@@ -129,8 +216,26 @@
 	struct proc *p;
 	int flags;
 {
-	int error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
+	int error;
+
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0) {
+		jazz_tlbmap_t tlbmap;
+		bus_size_t off;
+
+		tlbmap = (jazz_tlbmap_t)map->_dm_cookie;
+		off = jazz_dma_page_offs(buf);
+		jazz_dmatlb_map_va(p, (vaddr_t)buf, buflen, tlbmap->ptebase);
+
+		map->dm_segs[0].ds_addr = tlbmap->vaddr + off;
+		map->dm_segs[0].ds_len = buflen;
+		map->dm_segs[0]._ds_vaddr = (vaddr_t)buf;
+		map->dm_mapsize = buflen;
+		map->dm_nsegs = 1;
 
+		return (0);
+	}
+
+	error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
 	if (error == 0) {
 		error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
 		    map->dm_nsegs, map->_dm_boundary, p, flags);
@@ -148,8 +253,12 @@
 	struct mbuf *m0;
 	int flags;
 {
-	int error = _bus_dmamap_load_mbuf(t, map, m0, flags);
+	int error;
+
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0)
+		return (ENODEV); /* XXX which errno is better? */
 
+	error = _bus_dmamap_load_mbuf(t, map, m0, flags);
 	if (error == 0) {
 		error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
 		    map->dm_nsegs, map->_dm_boundary, NULL, flags);
@@ -167,8 +276,12 @@
 	struct uio *uio;
 	int flags;
 {
-	int error = jazz_bus_dmamap_load_uio(t, map, uio, flags);
+	int error;
 
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0)
+		return (ENODEV); /* XXX which errno is better? */
+
+	error = jazz_bus_dmamap_load_uio(t, map, uio, flags);
 	if (error == 0) {
 		error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
 		    map->dm_nsegs, map->_dm_boundary,
@@ -190,8 +303,12 @@
 	bus_size_t size;
 	int flags;
 {
-	int error = _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags);
+	int error;
+
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0)
+		return (ENODEV); /* XXX which errno is better? */
 
+	error = _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags);
 	if (error == 0) {
 		error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
 		    map->dm_nsegs, map->_dm_boundary, NULL, flags);
@@ -207,6 +324,13 @@
 	bus_dma_tag_t t;
 	bus_dmamap_t map;
 {
+	if ((map->_dm_flags & BUS_DMA_ALLOCNOW) != 0) {
+		map->dm_mapsize = 0;
+		map->dm_nsegs = 0;
+		map->_dm_flags &= ~BUS_DMA_ALLOCNOW;
+		return;
+	}
+
 	jazz_bus_dmamap_free_sgmap(t, map->dm_segs, map->dm_nsegs);
 	_bus_dmamap_unload(t, map);
 }
Index: jazz/fdc_jazzio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/fdc_jazzio.c,v
retrieving revision 1.5
diff -u -r1.5 fdc_jazzio.c
--- jazz/fdc_jazzio.c	2002/12/28 16:25:39	1.5
+++ jazz/fdc_jazzio.c	2003/01/19 10:06:52
@@ -80,23 +80,15 @@
 #include <sys/systm.h>
 #include <sys/callout.h>
 #include <sys/device.h>
-#include <sys/buf.h>
-#include <sys/queue.h>
 
-#include <mips/cache.h>
-
 #include <machine/autoconf.h>
 #include <machine/bus.h>
-#include <machine/cpu.h>
 
-#include <arc/jazz/jazzdmatlbreg.h>
 #include <arc/jazz/fdreg.h>
 #include <arc/jazz/fdcvar.h>
 #include <arc/jazz/jazziovar.h>
 #include <arc/jazz/dma.h>
 
-#include "locators.h"
-
 /* controller driver configuration */
 int fdc_jazzio_probe(struct device *, struct cfdata *, void *);
 void fdc_jazzio_attach(struct device *, struct device *, void *);
@@ -111,8 +103,11 @@
 	struct fdc_softc sc_fdc;	/* base fdc device */
 
 	bus_space_handle_t sc_baseioh;	/* base I/O handle */
-	struct dma_softc __dma;
-	struct dma_softc *dma;
+	bus_space_handle_t sc_dmaioh;	/* dma I/O handle */
+
+	bus_dma_tag_t sc_dmat;		/* bus dma tag */
+	bus_dmamap_t sc_dmamap;		/* bus dma map */
+	int sc_datain;			/* data direction */
 };
 
 CFATTACH_DECL(fdc_jazzio, sizeof(struct fdc_jazzio_softc),
@@ -175,13 +170,12 @@
 
 	fdc->sc_iot = ja->ja_bust;
 
-	fdc->sc_maxiosize = 4096; /* XXX */
+	fdc->sc_maxiosize = MAXPHYS;
 	fdc->sc_dma_start = fdc_jazzio_dma_start;
 	fdc->sc_dma_abort = fdc_jazzio_dma_abort;
 	fdc->sc_dma_done = fdc_jazzio_dma_done;
 
-	jsc->dma = &jsc->__dma;
-	fdc_dma_init(jsc->dma);
+	jsc->sc_dmat = ja->ja_dmat;
 
 	if (bus_space_map(fdc->sc_iot, ja->ja_addr,
 	    FDC_OFFSET + FDC_NPORT, 0, &jsc->sc_baseioh)) {
@@ -192,16 +186,32 @@
 	if (bus_space_subregion(fdc->sc_iot, jsc->sc_baseioh,
 	    FDC_OFFSET, FDC_NPORT, &fdc->sc_ioh)) {
 		printf(": unable to subregion I/O space\n");
-		bus_space_unmap(fdc->sc_iot, jsc->sc_baseioh,
-		    FDC_OFFSET + FDC_NPORT);
-		return;
+		goto out_unmap1;
 	}
 
+	if (bus_space_map(fdc->sc_iot, jazzio_conf->jc_fdcdmareg,
+	    R4030_DMA_RANGE, 0, &jsc->sc_dmaioh)) {
+		printf(": unable to map dma I/O space\n");
+		goto out_unmap1;
+	}
+
+	if (bus_dmamap_create(jsc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
+	    BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, &jsc->sc_dmamap)) {
+		printf(": unable to create DMA map\n");
+		goto out_unmap2;
+	}
+
 	printf("\n");
 
 	jazzio_intr_establish(ja->ja_intr, fdcintr, fdc);
 
 	fdcattach(fdc);
+	return;
+
+ out_unmap2:
+	bus_space_unmap(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_RANGE);
+ out_unmap1:
+	bus_space_unmap(fdc->sc_iot, jsc->sc_baseioh, FDC_OFFSET + FDC_NPORT);
 }
 
 void
@@ -213,8 +223,31 @@
 {
 	struct fdc_jazzio_softc *jsc = (void *)fdc;
 
-	mips_dcache_wbinv_range((vaddr_t)addr, (vsize_t)size);
-	DMA_START(jsc->dma, addr, size, datain ? DMA_FROM_DEV : DMA_TO_DEV);
+	/* halt DMA */
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_MODE, 0);
+
+	jsc->sc_datain = datain;
+
+	bus_dmamap_load(jsc->sc_dmat, jsc->sc_dmamap, addr, size, NULL,
+	    BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
+	    (datain ? BUS_DMA_READ : BUS_DMA_WRITE));
+	bus_dmamap_sync(jsc->sc_dmat, jsc->sc_dmamap,
+	    0, jsc->sc_dmamap->dm_mapsize,
+	    datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
+	/* load new transfer parameters */
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh,
+	    R4030_DMA_ADDR, jsc->sc_dmamap->dm_segs[0].ds_addr);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh,
+	    R4030_DMA_COUNT, jsc->sc_dmamap->dm_segs[0].ds_len);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh,
+	    R4030_DMA_MODE, R4030_DMA_MODE_160NS | R4030_DMA_MODE_8);
+
+	/* start DMA */
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh,
+	    R4030_DMA_ENAB, R4030_DMA_ENAB_RUN |
+	    (datain ? R4030_DMA_ENAB_READ : R4030_DMA_ENAB_WRITE));
 }
 
 void
@@ -223,7 +256,9 @@
 {
 	struct fdc_jazzio_softc *jsc = (void *)fdc;
 
-	DMA_RESET(jsc->dma);
+	/* halt DMA */
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_MODE, 0);
 }
 
 void
@@ -232,5 +267,13 @@
 {
 	struct fdc_jazzio_softc *jsc = (void *)fdc;
 
-	DMA_END(jsc->dma);
+	/* halt DMA */
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_COUNT, 0);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(fdc->sc_iot, jsc->sc_dmaioh, R4030_DMA_MODE, 0);
+
+	bus_dmamap_sync(jsc->sc_dmat, jsc->sc_dmamap,
+	    0, jsc->sc_dmamap->dm_mapsize,
+	    jsc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+	bus_dmamap_unload(jsc->sc_dmat, jsc->sc_dmamap);
 }
Index: arc/p_acer_pica_61.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/p_acer_pica_61.c,v
retrieving revision 1.3
diff -u -r1.3 p_acer_pica_61.c
--- arc/p_acer_pica_61.c	2002/12/28 16:44:44	1.3
+++ arc/p_acer_pica_61.c	2003/01/19 10:06:48
@@ -38,16 +38,6 @@
 #include <arc/jazz/pica.h>
 #include <arc/jazz/jazziovar.h>
 
-#include "asc.h"
-#if NASC > 0
-#include <arc/jazz/ascvar.h>
-
-struct asc_config asc_acer_pica_61_conf = {
-	&asc_timing_25mhz,
-	0,
-};
-#endif
-
 /* ALI PICA 61 and some MAGNUM? */
 
 void p_acer_pica_61_init __P((void));
@@ -106,8 +96,4 @@
 
 	/* chipset-dependent jazzio bus configuration */
 	jazzio_devconfig = acer_pica_61_cpu;
-
-#if NASC > 0
-	asc_conf = &asc_acer_pica_61_conf;
-#endif
 }
Index: arc/p_ms_jazz.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/p_ms_jazz.c,v
retrieving revision 1.3
diff -u -r1.3 p_ms_jazz.c
--- arc/p_ms_jazz.c	2002/12/28 16:44:44	1.3
+++ arc/p_ms_jazz.c	2003/01/19 10:06:48
@@ -39,12 +39,6 @@
 
 #include "com.h"
 
-#include "asc.h"
-#if NASC > 0
-#include <arc/jazz/ascreg.h>
-#include <arc/jazz/ascvar.h>
-#endif
-
 /* MAGNUM. NEC goes here too. */
 
 #ifndef COM_FREQ_MAGNUM
@@ -55,15 +49,6 @@
 #endif
 #endif /* COM_FREQ_MAGNUM */
 
-#if NASC > 0
-struct asc_config asc_ms_jazz_conf = {
-	&asc_timing_40mhz,
-
-	/* only if EPL is FE (Feature Enable bit for 53CF94) */
-	ASC_CNFG3_FCLK, /* clock 40MHz */
-};
-#endif
-
 void p_ms_jazz_init __P((void));
 
 struct platform platform_microsoft_jazz = {
@@ -111,10 +96,6 @@
 
 	/* jazzio bus configuration */
 	jazzio_devconfig = mips_magnum_r4000_cpu;
-
-#if NASC > 0
-	asc_conf = &asc_ms_jazz_conf;
-#endif
 
 #if NCOM > 0
 	com_freq = COM_FREQ_MAGNUM;
Index: conf/files.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/files.arc,v
retrieving revision 1.41
diff -u -r1.41 files.arc
--- conf/files.arc	2002/11/30 19:23:46	1.41
+++ conf/files.arc	2003/01/08 17:03:06
@@ -114,7 +114,7 @@
 device	jazzio {}
 attach	jazzio at mainbus		# optional
 file	arch/arc/jazz/jazzio.c		jazzio
-file	arch/arc/jazz/dma.c		# XXX jazzio
+#file	arch/arc/jazz/dma.c		# XXX jazzio
 file	arch/arc/jazz/jazzdmatlb.c	# XXX jazzio
 file	arch/arc/jazz/bus_dma_jazz.c	# XXX jazzio
 
@@ -160,7 +160,7 @@
 include	"dev/scsipi/files.scsipi"
 
 #	Symbios 53C94 SCSI interface driver on Jazz-Internal bus
-device	asc: scsi
+device	asc: scsi, ncr53c9x
 attach	asc at jazzio
 file	arch/arc/jazz/asc.c		asc	needs-flag
 
Index: jazz/dma.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/dma.h,v
retrieving revision 1.2
diff -u -r1.2 dma.h
--- jazz/dma.h	2001/07/24 16:26:53	1.2
+++ jazz/dma.h	2003/01/19 10:06:52
@@ -34,83 +34,34 @@
 /*
  *  Hardware dma registers.
  */
-typedef volatile struct {
-	int32_t		dma_mode;
-	int32_t		pad1;
-	int32_t		dma_enab;
-	int32_t		pad2;
-	int32_t		dma_count;
-	int32_t		pad3;
-	int32_t		dma_addr;
-	int32_t		pad4;
-} DmaReg, *pDmaReg;
 
-#define	R4030_DMA_MODE_40NS	0x00	/* Device dma timing */
-#define	R4030_DMA_MODE_80NS	0x01	/* Device dma timing */
-#define	R4030_DMA_MODE_120NS	0x02	/* Device dma timing */
-#define	R4030_DMA_MODE_160NS	0x03	/* Device dma timing */
-#define	R4030_DMA_MODE_200NS	0x04	/* Device dma timing */
-#define	R4030_DMA_MODE_240NS	0x05	/* Device dma timing */
-#define	R4030_DMA_MODE_280NS	0x06	/* Device dma timing */
-#define	R4030_DMA_MODE_320NS	0x07	/* Device dma timing */
-#define	R4030_DMA_MODE_8		0x08	/* Device 8 bit  */
-#define	R4030_DMA_MODE_16	0x10	/* Device 16 bit */
-#define	R4030_DMA_MODE_32	0x18	/* Device 32 bit */
-#define	R4030_DMA_MODE_INT	0x20	/* Interrupt when done */
-#define	R4030_DMA_MODE_BURST	0x40	/* Burst mode (Rev 2 only) */
-#define R4030_DMA_MODE_FAST	0x80	/* Fast dma cycle (Rev 2 only) */
-#define R4030_DMA_MODE		0xff	/* Mode register bits */
-#define DMA_DIR_WRITE		0x100	/* Software direction status */
-#define DMA_DIR_READ		0x000	/* Software direction status */
+#define R4030_DMA_MODE		0x00
+#define  R4030_DMA_MODE_40NS	0x00	/* Device dma timing */
+#define  R4030_DMA_MODE_80NS	0x01	/* Device dma timing */
+#define  R4030_DMA_MODE_120NS	0x02	/* Device dma timing */
+#define  R4030_DMA_MODE_160NS	0x03	/* Device dma timing */
+#define  R4030_DMA_MODE_200NS	0x04	/* Device dma timing */
+#define  R4030_DMA_MODE_240NS	0x05	/* Device dma timing */
+#define  R4030_DMA_MODE_280NS	0x06	/* Device dma timing */
+#define  R4030_DMA_MODE_320NS	0x07	/* Device dma timing */
+#define  R4030_DMA_MODE_8	0x08	/* Device 8 bit  */
+#define  R4030_DMA_MODE_16	0x10	/* Device 16 bit */
+#define  R4030_DMA_MODE_32	0x18	/* Device 32 bit */
+#define  R4030_DMA_MODE_INT	0x20	/* Interrupt when done */
+#define  R4030_DMA_MODE_BURST	0x40	/* Burst mode (Rev 2 only) */
+#define  R4030_DMA_MODE_FAST	0x80	/* Fast dma cycle (Rev 2 only) */
+
+#define R4030_DMA_ENAB		0x08
+#define  R4030_DMA_ENAB_RUN	0x0001	/* Enable dma */
+#define  R4030_DMA_ENAB_READ	0x0000	/* Read from device */
+#define  R4030_DMA_ENAB_WRITE	0x0002	/* Write to device */
+#define  R4030_DMA_ENAB_TC_IE	0x0100	/* Terminal count int enable */
+#define  R4030_DMA_ENAB_ME_IE	0x0200	/* Memory error int enable */
+#define  R4030_DMA_ENAB_TL_IE	0x0400	/* Translation limit int enable */
 
-#define	R4030_DMA_ENAB_RUN	0x01	/* Enable dma */
-#define	R4030_DMA_ENAB_READ	0x00	/* Read from device */
-#define	R4030_DMA_ENAB_WRITE	0x02	/* Write to device */
-#define	R4030_DMA_ENAB_TC_IE	0x100	/* Terminal count int enable */
-#define	R4030_DMA_ENAB_ME_IE	0x200	/* Memory error int enable */
-#define	R4030_DMA_ENAB_TL_IE	0x400	/* Translation limit int enable */
+#define R4030_DMA_COUNT	0x10
+#define  R4030_DMA_COUNT_MASK	0x000fffff /* Byte count mask */
 
-#define	R4030_DMA_COUNT_MASK	0x000fffff /* Byte count mask */
+#define	R4030_DMA_ADDR	0x18
 
-/*
- *  Structure used to control dma.
- */
-
-typedef struct dma_softc {
-	struct device	sc_dev;		/* use as a device */
-	struct esp_softc *sc_esp;
-	bus_addr_t	dma_va;		/* Viritual address for transfer */
-	int		mode;		/* Mode register value and direction */
-	jazz_dma_pte_t	*pte_base;	/* Pointer to dma tlb array */
-	int		pte_size;	/* Size of pte allocated pte array */
-	pDmaReg		dma_reg;	/* Pointer to dma registers */
-	int		sc_active;	/* Active flag */
-	void (*reset)(struct dma_softc *);	/* Reset routine pointer */
-	void (*enintr)(struct dma_softc *);	/* Int enab routine pointer */
-	void (*map)(struct dma_softc *, char *, size_t, int);
-						/* Map a dma viritual area */
-	void (*start)(struct dma_softc *, caddr_t, size_t, int);
-						/* Start routine pointer */
-	int (*isintr)(struct dma_softc *);	/* Int check routine pointer */
-	int (*intr)(struct dma_softc *);	/* Interrupt routine pointer */
-	void (*end)(struct dma_softc *);	/* Interrupt routine pointer */
-} dma_softc_t;
-
-#define	DMA_TO_DEV	0
-#define	DMA_FROM_DEV	1
-
-#define	DMA_RESET(r)		((r->reset)(r))
-#define	DMA_START(a, b, c, d)	((a->start)(a, b, c, d))
-#define	DMA_MAP(a, b, c, d)	((a->map)(a, b, c, d))
-#define	DMA_INTR(r)		((r->intr)(r))
-#define	DMA_DRAIN(r)
-#define	DMA_END(r)		((r->end)(r))
-
-void picaDmaInit __P((void));
-void picaDmaTLBAlloc __P((dma_softc_t *));
-void picaDmaTLBFree __P((dma_softc_t *));
-void picaDmaMap __P((struct dma_softc *, char *, size_t, int));
-void picaDmaStart __P((struct dma_softc *, char *, size_t, int));
-void picaDmaFlush __P((struct dma_softc *, char *, size_t, int));
-void asc_dma_init __P((struct dma_softc *));
-void fdc_dma_init __P((struct dma_softc *));
+#define	R4030_DMA_RANGE	0x20
Index: jazz/jazzio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/jazzio.c,v
retrieving revision 1.8
diff -u -r1.8 jazzio.c
--- jazz/jazzio.c	2003/01/01 00:32:05	1.8
+++ jazz/jazzio.c	2003/01/19 10:06:52
@@ -42,6 +42,7 @@
 #include <arc/jazz/jazziovar.h>
 #include <arc/jazz/pica.h>
 #include <arc/jazz/jazzdmatlbreg.h>
+#include <arc/jazz/jazzdmatlbvar.h>
 #include <arc/jazz/dma.h>
 #include <arc/jazz/pckbc_jazzioreg.h>
 
@@ -145,8 +146,8 @@
 
 	sc->sc_bus.ab_dv = (struct device *)sc;
 
-	/* Initialize PICA Dma */
-	picaDmaInit();
+	/* Initialize jazzio dma mapping register area and pool */
+	jazz_dmatlb_init(&jazzio_bus, jazzio_conf->jc_dmatlbreg);
 
 	/* Create bus_dma_tag */
 	jazz_bus_dma_tag_init(&sc->sc_dmat);
--- /dev/null	Sun Jan 19 14:24:37 2003
+++ jazz/asc.c	Sat Jan 11 03:20:00 2003
@@ -0,0 +1,441 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2003 Izumi Tsutsui.  All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsiconf.h>
+
+#include <arc/jazz/jazziovar.h>
+#include <arc/jazz/dma.h>
+#include <arc/jazz/pica.h>
+
+#include <dev/ic/ncr53c9xreg.h>
+#include <dev/ic/ncr53c9xvar.h>
+
+#define ASC_NPORTS	0x10
+#define ASC_ID_53CF94	0xa2	/* XXX should be in MI ncr53c9xreg.h */
+
+struct asc_softc {
+	struct ncr53c9x_softc sc_ncr53c9x;	/* glue to MI code */
+
+	bus_space_tag_t sc_iot;		/* bus space tag */
+	bus_space_handle_t sc_ioh;	/* bus space handle */
+	bus_space_handle_t sc_dmaioh;	/* bus space handle for DMAC */
+
+	bus_dma_tag_t sc_dmat;		/* DMA tag */
+	bus_dmamap_t sc_dmamap;		/* DMA map for transfers */
+
+	int     sc_active;              /* DMA state */
+	int     sc_datain;              /* DMA Data Direction */
+	size_t  sc_dmasize;             /* DMA size */
+	char    **sc_dmaaddr;           /* DMA address */
+	size_t  *sc_dmalen;             /* DMA length */
+};
+
+/*
+ * Autoconfiguration data for config.
+ */
+int asc_match(struct device *, struct cfdata *, void *);
+void asc_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(asc, sizeof(struct asc_softc),
+    asc_match, asc_attach, NULL, NULL);
+
+/*
+ *  Functions and the switch for the MI code.
+ */
+u_char asc_read_reg(struct ncr53c9x_softc *, int);
+void asc_write_reg(struct ncr53c9x_softc *, int, u_char);
+int asc_dma_isintr(struct ncr53c9x_softc *);
+void asc_dma_reset(struct ncr53c9x_softc *);
+int asc_dma_intr(struct ncr53c9x_softc *);
+int asc_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *, int, size_t *);
+void asc_dma_go(struct ncr53c9x_softc *);
+void asc_dma_stop(struct ncr53c9x_softc *);
+int asc_dma_isactive(struct ncr53c9x_softc *);
+
+struct ncr53c9x_glue asc_glue = {
+	asc_read_reg,
+	asc_write_reg,
+	asc_dma_isintr,
+	asc_dma_reset,
+	asc_dma_intr,
+	asc_dma_setup,
+	asc_dma_go,
+	asc_dma_stop,
+	asc_dma_isactive,
+	NULL			/* gl_clear_latched_intr */
+};
+
+/*
+ * Match driver based on name
+ */
+int
+asc_match(parent, match, aux)
+	struct device *parent;
+	struct cfdata *match;
+	void *aux;
+{
+	struct jazzio_attach_args *ja = aux;
+
+	if (strcmp(ja->ja_name, "ESP216") != 0)
+		return (0);
+	return (1);
+}
+
+void
+asc_attach(parent, self, aux)
+	struct device *parent;
+	struct device *self;
+	void *aux;
+{
+	struct jazzio_attach_args *ja = aux;
+	struct asc_softc *asc = (void *)self;
+	struct ncr53c9x_softc *sc = &asc->sc_ncr53c9x;
+	bus_space_tag_t iot;
+
+#if 0
+	/* Need info from platform dependent config?? */
+	if (asc_conf == NULL)
+		panic("asc_conf isn't initialized");
+#endif
+
+	sc->sc_glue = &asc_glue;
+
+	asc->sc_iot = iot = ja->ja_bust;
+	asc->sc_dmat = ja->ja_dmat;
+
+	if (bus_space_map(iot, ja->ja_addr, ASC_NPORTS, 0, &asc->sc_ioh)) {
+		printf(": unable to map I/O space\n");
+		return;
+	}
+
+	if (bus_space_map(iot, R4030_SYS_DMA0_REGS, R4030_DMA_RANGE,
+	    0, &asc->sc_dmaioh)) {
+		printf(": unable to map dma I/O space\n");
+		goto out1;
+	}
+
+	if (bus_dmamap_create(asc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
+	    BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, &asc->sc_dmamap)) {
+		printf(": unable to create DMA map\n");
+		goto out2;
+	}
+
+	/*
+	 * XXX More of this should be in ncr53c9x_attach(), but
+	 * XXX should we really poke around the chip that much in
+	 * XXX the MI code?  Think about this more...
+	 */
+
+	/*
+	 * Set up static configuration info.
+	 */
+	sc->sc_id = 7; /* XXX should be taken from ARC BIOS */
+	sc->sc_rev = NCR_VARIANT_NCR53C94;
+	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
+
+	/* identify 53CF9x-2 or not */
+	asc_write_reg(sc, NCR_CMD, NCRCMD_RSTCHIP);
+	DELAY(25);
+	asc_write_reg(sc, NCR_CMD, NCRCMD_DMA | NCRCMD_NOP);
+	DELAY(25);
+	asc_write_reg(sc, NCR_CFG2, NCRCFG2_FE);
+	DELAY(25);
+	asc_write_reg(sc, NCR_CMD, NCRCMD_DMA | NCRCMD_NOP);
+	DELAY(25);
+	if (asc_read_reg(sc, NCR_TCH) == ASC_ID_53CF94) {
+		sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE;
+		sc->sc_cfg3 = NCRF9XCFG3_IDM | NCRF9XCFG3_FCLK;
+		sc->sc_features = NCR_F_FASTSCSI;
+		sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
+		sc->sc_freq = 40; /* MHz */
+		sc->sc_maxxfer = 16 * 1024 * 1024;
+	} else {
+		sc->sc_rev = NCR_VARIANT_NCR53C94;
+		sc->sc_freq = 25; /* MHz */
+		sc->sc_maxxfer = 64 * 1024;
+	}
+
+	/*
+	 * XXX minsync and maxxfer _should_ be set up in MI code,
+	 * XXX but it appears to have some dependency on what sort
+	 * XXX of DMA we're hooked up to, etc.
+	 */
+
+	/*
+	 * This is the value used to start sync negotiations
+	 * Note that the NCR register "SYNCTP" is programmed
+	 * in "clocks per byte", and has a minimum value of 4.
+	 * The SCSI period used in negotiation is one-fourth
+	 * of the time (in nanoseconds) needed to transfer one byte.
+	 * Since the chip's clock is given in MHz, we have the following
+	 * formula: 4 * period = (1000 / freq) * 4
+	 */
+	sc->sc_minsync = 1000 / sc->sc_freq;
+
+	/* establish interrupt */
+	jazzio_intr_establish(ja->ja_intr, ncr53c9x_intr, asc);
+
+	/* Do the common parts of attachment. */
+	sc->sc_adapter.adapt_minphys = minphys;
+	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
+	ncr53c9x_attach(sc);
+
+	/* Turn on target selection using the `dma' method */
+	sc->sc_features |= NCR_F_DMASELECT;
+	return;
+
+ out2:
+	bus_space_unmap(iot, asc->sc_dmaioh, R4030_DMA_RANGE);
+ out1:
+	bus_space_unmap(iot, asc->sc_ioh, ASC_NPORTS);
+}
+
+/*
+ * Glue functions.
+ */
+
+u_char
+asc_read_reg(sc, reg)
+	struct ncr53c9x_softc *sc;
+	int reg;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	return bus_space_read_1(asc->sc_iot, asc->sc_ioh, reg);
+}
+
+void
+asc_write_reg(sc, reg, val)
+	struct ncr53c9x_softc *sc;
+	int reg;
+	u_char val;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	bus_space_write_1(asc->sc_iot, asc->sc_ioh, reg, val);
+}
+
+int
+asc_dma_isintr(sc)
+	struct ncr53c9x_softc *sc;
+{
+
+	return asc_read_reg(sc, NCR_STAT) & NCRSTAT_INT;
+}
+
+void
+asc_dma_reset(sc)
+	struct ncr53c9x_softc *sc;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	/* halt DMA */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0);
+}
+
+int
+asc_dma_intr(sc)
+	struct ncr53c9x_softc *sc;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+	int datain, resid, trans;
+
+	datain = asc->sc_datain;
+
+#ifdef DIAGNOSTIC
+	/* This is an "assertion" :) */
+	if (asc->sc_active == 0)
+		panic("asc_dma_intr: DMA wasn't active");
+#endif
+
+	/* DMA has stopped */
+
+	asc->sc_active = 0;
+
+	if (asc->sc_dmasize == 0) {
+		/* A "Transfer Pad" operation complete */
+		NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n",
+		    NCR_READ_REG(sc, NCR_TCL) |
+		    (NCR_READ_REG(sc, NCR_TCM) << 8),
+		    NCR_READ_REG(sc, NCR_TCL),
+		    NCR_READ_REG(sc, NCR_TCM)));
+
+		return 0;
+	}
+
+	resid = 0;
+
+	/*
+	 * If a transfer onto the SCSI bus gets interrupted by the device
+	 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
+	 * as residual since the ESP counter registers get decremented as
+	 * bytes are clocked into the FIFO.
+	 */
+	if (!datain &&
+	    (resid = (asc_read_reg(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
+		NCR_DMA(("asc_dma_intr: empty asc FIFO of %d ", resid));
+	}
+
+#if 0
+	if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
+		/* XXX need to drain residual data in FIFO? */
+	}
+#endif
+
+	/* halt DMA */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_COUNT, 0);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0);
+
+	bus_dmamap_sync(asc->sc_dmat, asc->sc_dmamap,
+	    0, asc->sc_dmamap->dm_mapsize,
+	    datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+	bus_dmamap_unload(asc->sc_dmat, asc->sc_dmamap);
+
+	trans = asc->sc_dmasize - resid;
+
+	if (trans < 0) {		/* transfered < 0 ? */
+#if 0
+		/*
+		 * This situation can happen in perfectly normal operation
+		 * if the ESP is reselected while using DMA to select
+		 * another target.  As such, don't print the warning.
+		 */
+		printf("%s: xfer (%d) > req (%d)\n",
+		    sc->sc_dev.dv_xname, trans, asc->sc_dmasize);
+#endif
+		trans = asc->sc_dmasize;
+	}
+	NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
+	    NCR_READ_REG(sc, NCR_TCL),
+	    NCR_READ_REG(sc, NCR_TCM),
+	    (sc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(sc, NCR_TCH) : 0,
+	    trans, resid));
+
+	*asc->sc_dmalen -= trans;
+	*asc->sc_dmaaddr += trans;
+
+	return 0;
+}
+
+int
+asc_dma_setup(sc, addr, len, datain, dmasize)
+	struct ncr53c9x_softc *sc;
+	caddr_t *addr;
+	size_t *len;
+	int datain;
+	size_t *dmasize;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	/* halt DMA */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0);
+
+	asc->sc_dmaaddr = addr;
+	asc->sc_dmalen = len;
+	asc->sc_dmasize = *dmasize;
+	asc->sc_datain = datain;
+
+	/*
+	 * No need to set up DMA in `Transfer Pad' operation.
+	 */
+	if (*dmasize == 0)
+		return 0;
+
+	bus_dmamap_load(asc->sc_dmat, asc->sc_dmamap, *addr, *len, NULL,
+	    ((sc->sc_nexus->xs->xs_control & XS_CTL_NOSLEEP) ?
+	    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
+	    (datain ? BUS_DMA_READ : BUS_DMA_WRITE));
+	bus_dmamap_sync(asc->sc_dmat, asc->sc_dmamap,
+	    0, asc->sc_dmamap->dm_mapsize,
+	    datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
+	return 0;
+}
+
+void
+asc_dma_go(sc)
+	struct ncr53c9x_softc *sc;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	/* No DMA transfer in Transfer Pad operation */
+	if (asc->sc_dmasize == 0)
+		return;
+
+	/* load transfer parameters */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh,
+	    R4030_DMA_ADDR, asc->sc_dmamap->dm_segs[0].ds_addr);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh,
+	    R4030_DMA_COUNT, asc->sc_dmamap->dm_segs[0].ds_len);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh,
+	    R4030_DMA_MODE, R4030_DMA_MODE_160NS | R4030_DMA_MODE_16);
+
+	/* start DMA */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh,
+	    R4030_DMA_ENAB, R4030_DMA_ENAB_RUN |
+	    (asc->sc_datain ? R4030_DMA_ENAB_READ : R4030_DMA_ENAB_WRITE));
+
+	asc->sc_active = 1;
+}
+
+void
+asc_dma_stop(sc)
+	struct ncr53c9x_softc *sc;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	/* halt DMA */
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0);
+	bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0);
+
+	asc->sc_active = 0;
+}
+
+int
+asc_dma_isactive(sc)
+	struct ncr53c9x_softc *sc;
+{
+	struct asc_softc *asc = (struct asc_softc *)sc;
+
+	return asc->sc_active;
+}