xref: /netbsd-src/sys/arch/amiga/dev/bzivsc.c (revision 40f7eaaf2596ce16adf343e6680d62b6ed6f12dd)
1*40f7eaafSjdolecek /*	$NetBSD: bzivsc.c,v 1.33 2019/01/08 19:41:09 jdolecek Exp $ */
206ff9502Smhitch 
306ff9502Smhitch /*
406ff9502Smhitch  * Copyright (c) 1997 Michael L. Hitch
506ff9502Smhitch  * Copyright (c) 1982, 1990 The Regents of the University of California.
606ff9502Smhitch  * All rights reserved.
706ff9502Smhitch  *
806ff9502Smhitch  * Redistribution and use in source and binary forms, with or without
906ff9502Smhitch  * modification, are permitted provided that the following conditions
1006ff9502Smhitch  * are met:
1106ff9502Smhitch  * 1. Redistributions of source code must retain the above copyright
1206ff9502Smhitch  *    notice, this list of conditions and the following disclaimer.
1306ff9502Smhitch  * 2. Redistributions in binary form must reproduce the above copyright
1406ff9502Smhitch  *    notice, this list of conditions and the following disclaimer in the
1506ff9502Smhitch  *    documentation and/or other materials provided with the distribution.
1678f74058Ssnj  * 3. Neither the name of the University nor the names of its contributors
1706ff9502Smhitch  *    may be used to endorse or promote products derived from this software
1806ff9502Smhitch  *    without specific prior written permission.
1906ff9502Smhitch  *
2006ff9502Smhitch  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2106ff9502Smhitch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2206ff9502Smhitch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2306ff9502Smhitch  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2406ff9502Smhitch  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2506ff9502Smhitch  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2606ff9502Smhitch  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2706ff9502Smhitch  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2806ff9502Smhitch  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2906ff9502Smhitch  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3006ff9502Smhitch  * SUCH DAMAGE.
3106ff9502Smhitch  *
3206ff9502Smhitch  */
3306ff9502Smhitch 
3423b820a8Sphx #ifdef __m68k__
35bd01b4a3Smrg #include "opt_m68k_arch.h"
3623b820a8Sphx #endif
37bd01b4a3Smrg 
381ea4df81Saymeric #include <sys/cdefs.h>
39*40f7eaafSjdolecek __KERNEL_RCSID(0, "$NetBSD: bzivsc.c,v 1.33 2019/01/08 19:41:09 jdolecek Exp $");
401ea4df81Saymeric 
4106ff9502Smhitch #include <sys/types.h>
4206ff9502Smhitch #include <sys/param.h>
4306ff9502Smhitch #include <sys/systm.h>
4406ff9502Smhitch #include <sys/kernel.h>
4506ff9502Smhitch #include <sys/errno.h>
4606ff9502Smhitch #include <sys/ioctl.h>
4706ff9502Smhitch #include <sys/device.h>
4806ff9502Smhitch #include <sys/buf.h>
4906ff9502Smhitch #include <sys/proc.h>
5006ff9502Smhitch #include <sys/queue.h>
5106ff9502Smhitch 
5206ff9502Smhitch #include <dev/scsipi/scsi_all.h>
5306ff9502Smhitch #include <dev/scsipi/scsipi_all.h>
5406ff9502Smhitch #include <dev/scsipi/scsiconf.h>
5506ff9502Smhitch #include <dev/scsipi/scsi_message.h>
5606ff9502Smhitch 
5706ff9502Smhitch #include <machine/cpu.h>
5806ff9502Smhitch 
5906ff9502Smhitch #include <dev/ic/ncr53c9xreg.h>
6006ff9502Smhitch #include <dev/ic/ncr53c9xvar.h>
6106ff9502Smhitch 
6206ff9502Smhitch #include <amiga/amiga/isr.h>
6306ff9502Smhitch #include <amiga/dev/bzivscvar.h>
6406ff9502Smhitch #include <amiga/dev/zbusvar.h>
6506ff9502Smhitch 
661ee8b50fSis #ifdef __powerpc__
671ee8b50fSis #define badaddr(a)      badaddr_read(a, 2, NULL)
681ee8b50fSis #endif
691ee8b50fSis 
7078a1d236Stsutsui int	bzivscmatch(device_t, cfdata_t, void *);
7178a1d236Stsutsui void	bzivscattach(device_t, device_t, void *);
7206ff9502Smhitch 
7306ff9502Smhitch /* Linkup to the rest of the kernel */
7478a1d236Stsutsui CFATTACH_DECL_NEW(bzivsc, sizeof(struct bzivsc_softc),
75c5e91d44Sthorpej     bzivscmatch, bzivscattach, NULL, NULL);
7606ff9502Smhitch 
7706ff9502Smhitch /*
7806ff9502Smhitch  * Functions and the switch for the MI code.
7906ff9502Smhitch  */
8078a1d236Stsutsui uint8_t	bzivsc_read_reg(struct ncr53c9x_softc *, int);
8178a1d236Stsutsui void	bzivsc_write_reg(struct ncr53c9x_softc *, int, uint8_t);
829382c873Saymeric int	bzivsc_dma_isintr(struct ncr53c9x_softc *);
839382c873Saymeric void	bzivsc_dma_reset(struct ncr53c9x_softc *);
849382c873Saymeric int	bzivsc_dma_intr(struct ncr53c9x_softc *);
8578a1d236Stsutsui int	bzivsc_dma_setup(struct ncr53c9x_softc *, uint8_t **,
869382c873Saymeric 	    size_t *, int, size_t *);
879382c873Saymeric void	bzivsc_dma_go(struct ncr53c9x_softc *);
889382c873Saymeric void	bzivsc_dma_stop(struct ncr53c9x_softc *);
899382c873Saymeric int	bzivsc_dma_isactive(struct ncr53c9x_softc *);
9006ff9502Smhitch 
9106ff9502Smhitch struct ncr53c9x_glue bzivsc_glue = {
9206ff9502Smhitch 	bzivsc_read_reg,
9306ff9502Smhitch 	bzivsc_write_reg,
9406ff9502Smhitch 	bzivsc_dma_isintr,
9506ff9502Smhitch 	bzivsc_dma_reset,
9606ff9502Smhitch 	bzivsc_dma_intr,
9706ff9502Smhitch 	bzivsc_dma_setup,
9806ff9502Smhitch 	bzivsc_dma_go,
9906ff9502Smhitch 	bzivsc_dma_stop,
10006ff9502Smhitch 	bzivsc_dma_isactive,
10178a1d236Stsutsui 	NULL,
10206ff9502Smhitch };
10306ff9502Smhitch 
10406ff9502Smhitch /* Maximum DMA transfer length to reduce impact on high-speed serial input */
10506ff9502Smhitch u_long bzivsc_max_dma = 1024;
10606ff9502Smhitch extern int ser_open_speed;
10706ff9502Smhitch 
10806ff9502Smhitch u_long bzivsc_cnt_pio = 0;	/* number of PIO transfers */
10906ff9502Smhitch u_long bzivsc_cnt_dma = 0;	/* number of DMA transfers */
11006ff9502Smhitch u_long bzivsc_cnt_dma2 = 0;	/* number of DMA transfers broken up */
11106ff9502Smhitch u_long bzivsc_cnt_dma3 = 0;	/* number of pages combined */
11206ff9502Smhitch 
11306ff9502Smhitch #ifdef DEBUG
11406ff9502Smhitch struct {
11578a1d236Stsutsui 	uint8_t hardbits;
11678a1d236Stsutsui 	uint8_t status;
11778a1d236Stsutsui 	uint8_t xx;
11878a1d236Stsutsui 	uint8_t yy;
11906ff9502Smhitch } bzivsc_trace[128];
12006ff9502Smhitch int bzivsc_trace_ptr = 0;
12106ff9502Smhitch int bzivsc_trace_enable = 1;
1229382c873Saymeric void bzivsc_dump(void);
12306ff9502Smhitch #endif
12406ff9502Smhitch 
12506ff9502Smhitch /*
12606ff9502Smhitch  * if we are a Phase5 Blizzard 12x0-IV
12706ff9502Smhitch  */
12806ff9502Smhitch int
bzivscmatch(device_t parent,cfdata_t cf,void * aux)12978a1d236Stsutsui bzivscmatch(device_t parent, cfdata_t cf, void *aux)
13006ff9502Smhitch {
13106ff9502Smhitch 	struct zbus_args *zap;
13278a1d236Stsutsui 	volatile uint8_t *regs;
13306ff9502Smhitch 
13406ff9502Smhitch 	zap = aux;
13506ff9502Smhitch 	if (zap->manid != 0x2140)
13678a1d236Stsutsui 		return 0;			/* It's not Phase 5 */
13706ff9502Smhitch 	if (zap->prodid != 11 && zap->prodid != 17)
13878a1d236Stsutsui 		return 0;			/* Not Blizzard 12x0 */
13906ff9502Smhitch 	if (!is_a1200())
14078a1d236Stsutsui 		return 0;			/* And not A1200 */
14106ff9502Smhitch 	regs = &((volatile u_char *)zap->va)[0x8000];
14253524e44Schristos 	if (badaddr((void *)__UNVOLATILE(regs)))
14378a1d236Stsutsui 		return 0;
14406ff9502Smhitch 	regs[NCR_CFG1 * 4] = 0;
14506ff9502Smhitch 	regs[NCR_CFG1 * 4] = NCRCFG1_PARENB | 7;
14606ff9502Smhitch 	delay(5);
14706ff9502Smhitch 	if (regs[NCR_CFG1 * 4] != (NCRCFG1_PARENB | 7))
14878a1d236Stsutsui 		return 0;
14978a1d236Stsutsui 	return 1;
15006ff9502Smhitch }
15106ff9502Smhitch 
15206ff9502Smhitch /*
15306ff9502Smhitch  * Attach this instance, and then all the sub-devices
15406ff9502Smhitch  */
15506ff9502Smhitch void
bzivscattach(device_t parent,device_t self,void * aux)15678a1d236Stsutsui bzivscattach(device_t parent, device_t self, void *aux)
15706ff9502Smhitch {
15878a1d236Stsutsui 	struct bzivsc_softc *bsc = device_private(self);
15906ff9502Smhitch 	struct ncr53c9x_softc *sc = &bsc->sc_ncr53c9x;
16006ff9502Smhitch 	struct zbus_args  *zap;
16106ff9502Smhitch 	extern u_long scsi_nosync;
16206ff9502Smhitch 	extern int shift_nosync;
16306ff9502Smhitch 	extern int ncr53c9x_debug;
16406ff9502Smhitch 
16506ff9502Smhitch 	/*
16606ff9502Smhitch 	 * Set up the glue for MI code early; we use some of it here.
16706ff9502Smhitch 	 */
16878a1d236Stsutsui 	sc->sc_dev = self;
16906ff9502Smhitch 	sc->sc_glue = &bzivsc_glue;
17006ff9502Smhitch 
17106ff9502Smhitch 	/*
17206ff9502Smhitch 	 * Save the regs
17306ff9502Smhitch 	 */
17406ff9502Smhitch 	zap = aux;
17578a1d236Stsutsui 	bsc->sc_reg = &((volatile uint8_t *)zap->va)[0x8000];
17606ff9502Smhitch 	bsc->sc_dmabase = &bsc->sc_reg[0x8000];
17706ff9502Smhitch 
178a1f606d3Slukem 	sc->sc_freq = 40;		/* Clocked at 40 MHz */
17906ff9502Smhitch 
18078a1d236Stsutsui 	aprint_normal(": address %p", bsc->sc_reg);
18106ff9502Smhitch 
18206ff9502Smhitch 	sc->sc_id = 7;
18306ff9502Smhitch 
18406ff9502Smhitch 	/*
18506ff9502Smhitch 	 * It is necessary to try to load the 2nd config register here,
18606ff9502Smhitch 	 * to find out what rev the FAS chip is, else the ncr53c9x_reset
18706ff9502Smhitch 	 * will not set up the defaults correctly.
18806ff9502Smhitch 	 */
18906ff9502Smhitch 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
19006ff9502Smhitch 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE;
19106ff9502Smhitch 	sc->sc_cfg3 = 0x08 /*FCLK*/ | NCRESPCFG3_FSCSI | NCRESPCFG3_CDB;
19206ff9502Smhitch 	sc->sc_rev = NCR_VARIANT_FAS216;
19306ff9502Smhitch 
19406ff9502Smhitch 	/*
19506ff9502Smhitch 	 * This is the value used to start sync negotiations
19606ff9502Smhitch 	 * Note that the NCR register "SYNCTP" is programmed
19706ff9502Smhitch 	 * in "clocks per byte", and has a minimum value of 4.
19806ff9502Smhitch 	 * The SCSI period used in negotiation is one-fourth
19906ff9502Smhitch 	 * of the time (in nanoseconds) needed to transfer one byte.
20006ff9502Smhitch 	 * Since the chip's clock is given in MHz, we have the following
20106ff9502Smhitch 	 * formula: 4 * period = (1000 / freq) * 4
20206ff9502Smhitch 	 */
20306ff9502Smhitch 	sc->sc_minsync = 1000 / sc->sc_freq;
20406ff9502Smhitch 
20506ff9502Smhitch 	/*
20606ff9502Smhitch 	 * get flags from -I argument and set cf_flags.
20706ff9502Smhitch 	 * NOTE: low 8 bits are to disable disconnect, and the next
20806ff9502Smhitch 	 *       8 bits are to disable sync.
20906ff9502Smhitch 	 */
21078a1d236Stsutsui 	device_cfdata(self)->cf_flags |= (scsi_nosync >> shift_nosync)
21106ff9502Smhitch 	    & 0xffff;
21206ff9502Smhitch 	shift_nosync += 16;
21306ff9502Smhitch 
21406ff9502Smhitch 	/* Use next 16 bits of -I argument to set ncr53c9x_debug flags */
21506ff9502Smhitch 	ncr53c9x_debug |= (scsi_nosync >> shift_nosync) & 0xffff;
21606ff9502Smhitch 	shift_nosync += 16;
21706ff9502Smhitch 
21806ff9502Smhitch #if 1
21906ff9502Smhitch 	if (((scsi_nosync >> shift_nosync) & 0xff00) == 0xff00)
22006ff9502Smhitch 		sc->sc_minsync = 0;
22106ff9502Smhitch #endif
22206ff9502Smhitch 
22306ff9502Smhitch 	/* Really no limit, but since we want to fit into the TCR... */
22406ff9502Smhitch 	sc->sc_maxxfer = 64 * 1024;
22506ff9502Smhitch 
22606ff9502Smhitch 	/*
22706ff9502Smhitch 	 * Configure interrupts.
22806ff9502Smhitch 	 */
2298c4d1bf1Stsutsui 	bsc->sc_isr.isr_intr = ncr53c9x_intr;
23006ff9502Smhitch 	bsc->sc_isr.isr_arg  = sc;
23106ff9502Smhitch 	bsc->sc_isr.isr_ipl  = 2;
23206ff9502Smhitch 	add_isr(&bsc->sc_isr);
23306ff9502Smhitch 
23406ff9502Smhitch 	/*
23506ff9502Smhitch 	 * Now try to attach all the sub-devices
23606ff9502Smhitch 	 */
237937a7a3eSbouyer 	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
238937a7a3eSbouyer 	sc->sc_adapter.adapt_minphys = minphys;
239937a7a3eSbouyer 	ncr53c9x_attach(sc);
24006ff9502Smhitch }
24106ff9502Smhitch 
24206ff9502Smhitch /*
24306ff9502Smhitch  * Glue functions.
24406ff9502Smhitch  */
24506ff9502Smhitch 
24678a1d236Stsutsui uint8_t
bzivsc_read_reg(struct ncr53c9x_softc * sc,int reg)2479382c873Saymeric bzivsc_read_reg(struct ncr53c9x_softc *sc, int reg)
24806ff9502Smhitch {
24906ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
25006ff9502Smhitch 
25106ff9502Smhitch 	return bsc->sc_reg[reg * 4];
25206ff9502Smhitch }
25306ff9502Smhitch 
25406ff9502Smhitch void
bzivsc_write_reg(struct ncr53c9x_softc * sc,int reg,uint8_t val)25578a1d236Stsutsui bzivsc_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val)
25606ff9502Smhitch {
25706ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
25878a1d236Stsutsui 	uint8_t v = val;
25906ff9502Smhitch 
26006ff9502Smhitch 	bsc->sc_reg[reg * 4] = v;
26106ff9502Smhitch #ifdef DEBUG
262e6c88a76Sthorpej if (bzivsc_trace_enable/* && sc->sc_nexus && sc->sc_nexus->xs->xs_control & XS_CTL_POLL */ &&
26306ff9502Smhitch   reg == NCR_CMD/* && bsc->sc_active*/) {
26406ff9502Smhitch   bzivsc_trace[(bzivsc_trace_ptr - 1) & 127].yy = v;
26506ff9502Smhitch /*  printf(" cmd %x", v);*/
26606ff9502Smhitch }
26706ff9502Smhitch #endif
26806ff9502Smhitch }
26906ff9502Smhitch 
27006ff9502Smhitch int
bzivsc_dma_isintr(struct ncr53c9x_softc * sc)2719382c873Saymeric bzivsc_dma_isintr(struct ncr53c9x_softc *sc)
27206ff9502Smhitch {
27306ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
27406ff9502Smhitch 
27506ff9502Smhitch 	if ((bsc->sc_reg[NCR_STAT * 4] & NCRSTAT_INT) == 0)
27606ff9502Smhitch 		return 0;
27706ff9502Smhitch 
27806ff9502Smhitch #ifdef DEBUG
279e6c88a76Sthorpej if (/*sc->sc_nexus && sc->sc_nexus->xs->xs_control & XS_CTL_POLL &&*/ bzivsc_trace_enable) {
28006ff9502Smhitch   bzivsc_trace[bzivsc_trace_ptr].status = bsc->sc_reg[NCR_STAT * 4];
28106ff9502Smhitch   bzivsc_trace[bzivsc_trace_ptr].xx = bsc->sc_reg[NCR_CMD * 4];
28206ff9502Smhitch   bzivsc_trace[bzivsc_trace_ptr].yy = bsc->sc_active;
28306ff9502Smhitch   bzivsc_trace_ptr = (bzivsc_trace_ptr + 1) & 127;
28406ff9502Smhitch }
28506ff9502Smhitch #endif
28606ff9502Smhitch 	return 1;
28706ff9502Smhitch }
28806ff9502Smhitch 
28906ff9502Smhitch void
bzivsc_dma_reset(struct ncr53c9x_softc * sc)2909382c873Saymeric bzivsc_dma_reset(struct ncr53c9x_softc *sc)
29106ff9502Smhitch {
29206ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
29306ff9502Smhitch 
29406ff9502Smhitch 	bsc->sc_active = 0;
29506ff9502Smhitch }
29606ff9502Smhitch 
29706ff9502Smhitch int
bzivsc_dma_intr(struct ncr53c9x_softc * sc)2989382c873Saymeric bzivsc_dma_intr(struct ncr53c9x_softc *sc)
29906ff9502Smhitch {
30006ff9502Smhitch 	register struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
30106ff9502Smhitch 	register int	cnt;
30206ff9502Smhitch 
30306ff9502Smhitch 	NCR_DMA(("bzivsc_dma_intr: cnt %d int %x stat %x fifo %d ",
30406ff9502Smhitch 	    bsc->sc_dmasize, sc->sc_espintr, sc->sc_espstat,
30506ff9502Smhitch 	    bsc->sc_reg[NCR_FFLAG * 4] & NCRFIFO_FF));
30606ff9502Smhitch 	if (bsc->sc_active == 0) {
30706ff9502Smhitch 		printf("bzivsc_intr--inactive DMA\n");
30806ff9502Smhitch 		return -1;
30906ff9502Smhitch 	}
31006ff9502Smhitch 
31106ff9502Smhitch 	/* update sc_dmaaddr and sc_pdmalen */
31206ff9502Smhitch 	cnt = bsc->sc_reg[NCR_TCL * 4];
31306ff9502Smhitch 	cnt += bsc->sc_reg[NCR_TCM * 4] << 8;
31406ff9502Smhitch 	cnt += bsc->sc_reg[NCR_TCH * 4] << 16;
31506ff9502Smhitch 	if (!bsc->sc_datain) {
31606ff9502Smhitch 		cnt += bsc->sc_reg[NCR_FFLAG * 4] & NCRFIFO_FF;
31706ff9502Smhitch 		bsc->sc_reg[NCR_CMD * 4] = NCRCMD_FLUSH;
31806ff9502Smhitch 	}
31906ff9502Smhitch 	cnt = bsc->sc_dmasize - cnt;	/* number of bytes transferred */
32006ff9502Smhitch 	NCR_DMA(("DMA xferred %d\n", cnt));
32106ff9502Smhitch 	if (bsc->sc_xfr_align) {
32278a1d236Stsutsui 		memcpy(*bsc->sc_dmaaddr, bsc->sc_alignbuf, cnt);
32306ff9502Smhitch 		bsc->sc_xfr_align = 0;
32406ff9502Smhitch 	}
32506ff9502Smhitch 	*bsc->sc_dmaaddr += cnt;
32606ff9502Smhitch 	*bsc->sc_pdmalen -= cnt;
32706ff9502Smhitch 	bsc->sc_active = 0;
32806ff9502Smhitch 	return 0;
32906ff9502Smhitch }
33006ff9502Smhitch 
33106ff9502Smhitch int
bzivsc_dma_setup(struct ncr53c9x_softc * sc,uint8_t ** addr,size_t * len,int datain,size_t * dmasize)33278a1d236Stsutsui bzivsc_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
3339382c873Saymeric                  int datain, size_t *dmasize)
33406ff9502Smhitch {
33506ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
336744246faSis 	paddr_t pa;
33778a1d236Stsutsui 	uint8_t *ptr;
33806ff9502Smhitch 	size_t xfer;
33906ff9502Smhitch 
34078a1d236Stsutsui 	bsc->sc_dmaaddr = addr;
34106ff9502Smhitch 	bsc->sc_pdmalen = len;
34206ff9502Smhitch 	bsc->sc_datain = datain;
34306ff9502Smhitch 	bsc->sc_dmasize = *dmasize;
34406ff9502Smhitch 	/*
34506ff9502Smhitch 	 * DMA can be nasty for high-speed serial input, so limit the
34606ff9502Smhitch 	 * size of this DMA operation if the serial port is running at
34706ff9502Smhitch 	 * a high speed (higher than 19200 for now - should be adjusted
348d20841bbSwiz 	 * based on CPU type and speed?).
34906ff9502Smhitch 	 * XXX - add serial speed check XXX
35006ff9502Smhitch 	 */
35106ff9502Smhitch 	if (ser_open_speed > 19200 && bzivsc_max_dma != 0 &&
35206ff9502Smhitch 	    bsc->sc_dmasize > bzivsc_max_dma)
35306ff9502Smhitch 		bsc->sc_dmasize = bzivsc_max_dma;
35406ff9502Smhitch 	ptr = *addr;			/* Kernel virtual address */
35506ff9502Smhitch 	pa = kvtop(ptr);		/* Physical address of DMA */
356d1579b2dSriastradh 	xfer = uimin(bsc->sc_dmasize, PAGE_SIZE - (pa & (PAGE_SIZE - 1)));
35706ff9502Smhitch 	bsc->sc_xfr_align = 0;
35806ff9502Smhitch 	/*
35906ff9502Smhitch 	 * If output and unaligned, stuff odd byte into FIFO
36006ff9502Smhitch 	 */
36106ff9502Smhitch 	if (datain == 0 && (int)ptr & 1) {
36206ff9502Smhitch 		NCR_DMA(("bzivsc_dma_setup: align byte written to fifo\n"));
36306ff9502Smhitch 		pa++;
36406ff9502Smhitch 		xfer--;			/* XXXX CHECK THIS !!!! XXXX */
36506ff9502Smhitch 		bsc->sc_reg[NCR_FIFO * 4] = *ptr++;
36606ff9502Smhitch 	}
36706ff9502Smhitch 	/*
36806ff9502Smhitch 	 * If unaligned address, read unaligned bytes into alignment buffer
36906ff9502Smhitch 	 */
37006ff9502Smhitch 	else if ((int)ptr & 1) {
37153524e44Schristos 		pa = kvtop((void *)&bsc->sc_alignbuf);
372d1579b2dSriastradh 		xfer = bsc->sc_dmasize = uimin(xfer, sizeof(bsc->sc_alignbuf));
37306ff9502Smhitch 		NCR_DMA(("bzivsc_dma_setup: align read by %d bytes\n", xfer));
37406ff9502Smhitch 		bsc->sc_xfr_align = 1;
37506ff9502Smhitch 	}
37606ff9502Smhitch ++bzivsc_cnt_dma;		/* number of DMA operations */
37706ff9502Smhitch 
37806ff9502Smhitch 	while (xfer < bsc->sc_dmasize) {
37978a1d236Stsutsui 		if ((pa + xfer) != kvtop(*addr + xfer))
38006ff9502Smhitch 			break;
3818818afa4Sthorpej 		if ((bsc->sc_dmasize - xfer) < PAGE_SIZE)
38206ff9502Smhitch 			xfer = bsc->sc_dmasize;
38306ff9502Smhitch 		else
3848818afa4Sthorpej 			xfer += PAGE_SIZE;
38506ff9502Smhitch ++bzivsc_cnt_dma3;
38606ff9502Smhitch 	}
38706ff9502Smhitch if (xfer != *len)
38806ff9502Smhitch   ++bzivsc_cnt_dma2;
38906ff9502Smhitch 
39006ff9502Smhitch 	bsc->sc_dmasize = xfer;
39106ff9502Smhitch 	*dmasize = bsc->sc_dmasize;
39206ff9502Smhitch 	bsc->sc_pa = pa;
39306ff9502Smhitch #if defined(M68040) || defined(M68060)
39406ff9502Smhitch 	if (mmutype == MMU_68040) {
39506ff9502Smhitch 		if (bsc->sc_xfr_align) {
39606ff9502Smhitch 			dma_cachectl(bsc->sc_alignbuf,
39706ff9502Smhitch 			    sizeof(bsc->sc_alignbuf));
39806ff9502Smhitch 		}
39906ff9502Smhitch 		else
40006ff9502Smhitch 			dma_cachectl(*bsc->sc_dmaaddr, bsc->sc_dmasize);
40106ff9502Smhitch 	}
40206ff9502Smhitch #endif
40306ff9502Smhitch 
40406ff9502Smhitch 	pa >>= 1;
40506ff9502Smhitch 	if (!bsc->sc_datain)
40606ff9502Smhitch 		pa |= 0x80000000;
40778a1d236Stsutsui 	bsc->sc_dmabase[0x8000] = (uint8_t)(pa >> 24);
40878a1d236Stsutsui 	bsc->sc_dmabase[0] = (uint8_t)(pa >> 24);
40978a1d236Stsutsui 	bsc->sc_dmabase[0] = (uint8_t)(pa >> 16);
41078a1d236Stsutsui 	bsc->sc_dmabase[0] = (uint8_t)(pa >> 8);
41178a1d236Stsutsui 	bsc->sc_dmabase[0] = (uint8_t)(pa);
41206ff9502Smhitch 	bsc->sc_active = 1;
41306ff9502Smhitch 	return 0;
41406ff9502Smhitch }
41506ff9502Smhitch 
41606ff9502Smhitch void
bzivsc_dma_go(struct ncr53c9x_softc * sc)4179382c873Saymeric bzivsc_dma_go(struct ncr53c9x_softc *sc)
41806ff9502Smhitch {
41906ff9502Smhitch }
42006ff9502Smhitch 
42106ff9502Smhitch void
bzivsc_dma_stop(struct ncr53c9x_softc * sc)4229382c873Saymeric bzivsc_dma_stop(struct ncr53c9x_softc *sc)
42306ff9502Smhitch {
42406ff9502Smhitch }
42506ff9502Smhitch 
42606ff9502Smhitch int
bzivsc_dma_isactive(struct ncr53c9x_softc * sc)4279382c873Saymeric bzivsc_dma_isactive(struct ncr53c9x_softc *sc)
42806ff9502Smhitch {
42906ff9502Smhitch 	struct bzivsc_softc *bsc = (struct bzivsc_softc *)sc;
43006ff9502Smhitch 
43106ff9502Smhitch 	return bsc->sc_active;
43206ff9502Smhitch }
43306ff9502Smhitch 
43406ff9502Smhitch #ifdef DEBUG
43506ff9502Smhitch void
bzivsc_dump(void)4369382c873Saymeric bzivsc_dump(void)
43706ff9502Smhitch {
43806ff9502Smhitch 	int i;
43906ff9502Smhitch 
44006ff9502Smhitch 	i = bzivsc_trace_ptr;
44106ff9502Smhitch 	printf("bzivsc_trace dump: ptr %x\n", bzivsc_trace_ptr);
44206ff9502Smhitch 	do {
44306ff9502Smhitch 		if (bzivsc_trace[i].hardbits == 0) {
44406ff9502Smhitch 			i = (i + 1) & 127;
44506ff9502Smhitch 			continue;
44606ff9502Smhitch 		}
44706ff9502Smhitch 		printf("%02x%02x%02x%02x(", bzivsc_trace[i].hardbits,
44806ff9502Smhitch 		    bzivsc_trace[i].status, bzivsc_trace[i].xx, bzivsc_trace[i].yy);
44906ff9502Smhitch 		if (bzivsc_trace[i].status & NCRSTAT_INT)
45006ff9502Smhitch 			printf("NCRINT/");
45106ff9502Smhitch 		if (bzivsc_trace[i].status & NCRSTAT_TC)
45206ff9502Smhitch 			printf("NCRTC/");
45306ff9502Smhitch 		switch(bzivsc_trace[i].status & NCRSTAT_PHASE) {
45406ff9502Smhitch 		case 0:
45506ff9502Smhitch 			printf("dataout"); break;
45606ff9502Smhitch 		case 1:
45706ff9502Smhitch 			printf("datain"); break;
45806ff9502Smhitch 		case 2:
45906ff9502Smhitch 			printf("cmdout"); break;
46006ff9502Smhitch 		case 3:
46106ff9502Smhitch 			printf("status"); break;
46206ff9502Smhitch 		case 6:
46306ff9502Smhitch 			printf("msgout"); break;
46406ff9502Smhitch 		case 7:
46506ff9502Smhitch 			printf("msgin"); break;
46606ff9502Smhitch 		default:
46706ff9502Smhitch 			printf("phase%d?", bzivsc_trace[i].status & NCRSTAT_PHASE);
46806ff9502Smhitch 		}
46906ff9502Smhitch 		printf(") ");
47006ff9502Smhitch 		i = (i + 1) & 127;
47106ff9502Smhitch 	} while (i != bzivsc_trace_ptr);
47206ff9502Smhitch 	printf("\n");
47306ff9502Smhitch }
47406ff9502Smhitch #endif
475