Home | History | Annotate | Line # | Download | only in dev
bzsc.c revision 1.2
      1 /*
      2  * Copyright (c) 1995 Daniel Widenfalk
      3  * Copyright (c) 1994 Christian E. Hopps
      4  * Copyright (c) 1982, 1990 The Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	@(#)dma.c
     36  */
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/kernel.h>
     41 #include <sys/device.h>
     42 #include <scsi/scsi_all.h>
     43 #include <scsi/scsiconf.h>
     44 #include <vm/vm.h>
     45 #include <vm/vm_kern.h>
     46 #include <vm/vm_page.h>
     47 #include <machine/pmap.h>
     48 #include <amiga/amiga/custom.h>
     49 #include <amiga/amiga/cc.h>
     50 #include <amiga/amiga/device.h>
     51 #include <amiga/amiga/isr.h>
     52 #include <amiga/dev/sfasreg.h>
     53 #include <amiga/dev/sfasvar.h>
     54 #include <amiga/dev/zbusvar.h>
     55 #include <amiga/dev/bzscreg.h>
     56 #include <amiga/dev/bzscvar.h>
     57 
     58 int  bzscprint  __P((void *auxp, char *));
     59 void bzscattach __P((struct device *, struct device *, void *));
     60 int  bzscmatch  __P((struct device *, struct cfdata *, void *));
     61 
     62 struct scsi_adapter bzsc_scsiswitch = {
     63 	sfas_scsicmd,
     64 	sfas_minphys,
     65 	0,			/* no lun support */
     66 	0,			/* no lun support */
     67 };
     68 
     69 struct scsi_device bzsc_scsidev = {
     70 	NULL,		/* use default error handler */
     71 	NULL,		/* do not have a start functio */
     72 	NULL,		/* have no async handler */
     73 	NULL,		/* Use default done routine */
     74 };
     75 
     76 
     77 struct cfdriver bzsccd = {
     78 	NULL, "bzsc", (cfmatch_t)bzscmatch, bzscattach,
     79 	DV_DULL, sizeof(struct bzsc_softc), NULL, 0 };
     80 
     81 int bzsc_intr		__P((struct sfas_softc *dev));
     82 int bzsc_setup_dma	__P((struct sfas_softc *sc, void *ptr, int len,
     83 			     int mode));
     84 int bzsc_build_dma_chain __P((struct sfas_softc *sc,
     85 				struct sfas_dma_chain *chain, void *p, int l));
     86 int bzsc_need_bump	__P((struct sfas_softc *sc, void *ptr, int len));
     87 void bzsc_led_dummy	__P((struct sfas_softc *sc));
     88 
     89 /*
     90  * if we are an Advanced Systems & Software FastlaneZ3
     91  */
     92 int bzscmatch(struct device *pdp, struct cfdata *cdp,	void *auxp)
     93 {
     94   struct zbus_args *zap;
     95 
     96   if (!is_a1200())
     97     return(0);
     98 
     99   zap = auxp;
    100   if (zap->manid == 0x2140 && zap->prodid == 11)
    101     return(1);
    102 
    103   return(0);
    104 }
    105 
    106 void bzscattach(struct device *pdp, struct device *dp, void *auxp)
    107 {
    108 	struct bzsc_softc *sc;
    109 	struct zbus_args  *zap;
    110 	bzsc_regmap_p	   rp;
    111 	u_int		  *pte, page;
    112 	vu_char		  *fas;
    113 
    114 	zap = auxp;
    115 	fas = (vu_char *)(((char *)zap->va)+0x10000);
    116 
    117 	sc = (struct bzsc_softc *)dp;
    118 	rp = &sc->sc_regmap;
    119 
    120 	rp->FAS216.sfas_tc_low   = &fas[0x00];
    121 	rp->FAS216.sfas_tc_mid   = &fas[0x02];
    122 	rp->FAS216.sfas_fifo     = &fas[0x04];
    123 	rp->FAS216.sfas_command  = &fas[0x06];
    124 	rp->FAS216.sfas_dest_id  = &fas[0x08];
    125 	rp->FAS216.sfas_timeout  = &fas[0x0A];
    126 	rp->FAS216.sfas_syncper  = &fas[0x0C];
    127 	rp->FAS216.sfas_syncoff  = &fas[0x0E];
    128 	rp->FAS216.sfas_config1  = &fas[0x10];
    129 	rp->FAS216.sfas_clkconv  = &fas[0x12];
    130 	rp->FAS216.sfas_test     = &fas[0x14];
    131 	rp->FAS216.sfas_config2  = &fas[0x16];
    132 	rp->FAS216.sfas_config3  = &fas[0x18];
    133 	rp->FAS216.sfas_tc_high  = &fas[0x1C];
    134 	rp->FAS216.sfas_fifo_bot = &fas[0x1E];
    135 	rp->cclkaddr		 = &fas[0x21];
    136 	rp->epowaddr		 = &fas[0x31];
    137 
    138 	sc->sc_softc.sc_fas  = (sfas_regmap_p)rp;
    139 	sc->sc_softc.sc_spec = 0;
    140 
    141 	sc->sc_softc.sc_led  = bzsc_led_dummy;
    142 
    143 	sc->sc_softc.sc_setup_dma	= bzsc_setup_dma;
    144 	sc->sc_softc.sc_build_dma_chain = bzsc_build_dma_chain;
    145 	sc->sc_softc.sc_need_bump	= bzsc_need_bump;
    146 
    147 	sc->sc_softc.sc_clock_freq   = 40; /* BlizzardII 1230 runs at 40MHz? */
    148 	sc->sc_softc.sc_timeout      = 250; /* Set default timeout to 250ms */
    149 	sc->sc_softc.sc_config_flags = 0;
    150 	sc->sc_softc.sc_host_id      = 7;
    151 
    152 	sc->sc_softc.sc_bump_sz = NBPG;
    153 	sc->sc_softc.sc_bump_pa = 0x0;
    154 
    155 	sfasinitialize((struct sfas_softc *)sc);
    156 
    157 	sc->sc_softc.sc_link.adapter_softc = sc;
    158 	sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
    159 	sc->sc_softc.sc_link.adapter = &bzsc_scsiswitch;
    160 	sc->sc_softc.sc_link.device = &bzsc_scsidev;
    161 	sc->sc_softc.sc_link.openings = 1;
    162 
    163 	printf("\n");
    164 
    165 	sc->sc_softc.sc_isr.isr_intr = bzsc_intr;
    166 	sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc;
    167 	sc->sc_softc.sc_isr.isr_ipl = 2;
    168 	add_isr(&sc->sc_softc.sc_isr);
    169 
    170 	/* attach all scsi units on us */
    171 	config_found(dp, &sc->sc_softc.sc_link, bzscprint);
    172 }
    173 
    174 /* print diag if pnp is NULL else just extra */
    175 int bzscprint(void *auxp, char *pnp)
    176 {
    177 	if (pnp == NULL)
    178 		return(UNCONF);
    179 
    180 	return(QUIET);
    181 }
    182 
    183 int bzsc_intr(struct sfas_softc *dev)
    184 {
    185 	bzsc_regmap_p	rp;
    186 	int		quickints;
    187 
    188 	rp = (bzsc_regmap_p)dev->sc_fas;
    189 
    190 	if (!(*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING))
    191 		return(0);
    192 
    193 	quickints = 16;
    194 	do {
    195 		dev->sc_status = *rp->FAS216.sfas_status;
    196 		dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
    197 
    198 		if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
    199 			dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
    200 			dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
    201 		}
    202 		sfasintr(dev);
    203 	} while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) &&
    204 		--quickints);
    205 
    206 	return(1);
    207 }
    208 
    209 /* --------- */
    210 void bzsc_set_dma_adr(struct sfas_softc *sc, void *ptr, int mode)
    211 {
    212 	bzsc_regmap_p	rp;
    213 	unsigned long	p;
    214 
    215 	rp = (bzsc_regmap_p)sc->sc_fas;
    216 
    217 	p = ((unsigned long)p)>>1;
    218 
    219 	if (mode == SFAS_DMA_WRITE)
    220 		p |= BZSC_DMA_WRITE;
    221 	else
    222 		p |= BZSC_DMA_READ;
    223 
    224 	*rp->epowaddr = (u_char)(p>>24) & 0xFF;
    225 	*rp->cclkaddr = (u_char)(p>>16) & 0xFF;
    226 	*rp->cclkaddr = (u_char)(p>> 8) & 0xFF;
    227 	*rp->cclkaddr = (u_char)(p    ) & 0xFF;
    228 }
    229 
    230 /* Set DMA transfer counter */
    231 void bzsc_set_dma_tc(struct sfas_softc *sc, unsigned int len)
    232 {
    233 	*sc->sc_fas->sfas_tc_low  = len; len >>= 8;
    234 	*sc->sc_fas->sfas_tc_mid  = len; len >>= 8;
    235 	*sc->sc_fas->sfas_tc_high = len;
    236 }
    237 
    238 /* Initialize DMA for transfer */
    239 int bzsc_setup_dma(struct sfas_softc *sc, void *ptr, int len, int mode)
    240 {
    241 	int	retval;
    242 
    243 	retval = 0;
    244 
    245 	switch(mode) {
    246 	case SFAS_DMA_READ:
    247 	case SFAS_DMA_WRITE:
    248 		bzsc_set_dma_adr(sc, ptr, mode);
    249 		bzsc_set_dma_tc(sc, len);
    250 		break;
    251 	case SFAS_DMA_CLEAR:
    252 	default:
    253 		retval = (*sc->sc_fas->sfas_tc_high << 16) |
    254 			 (*sc->sc_fas->sfas_tc_mid  <<  8) |
    255 			  *sc->sc_fas->sfas_tc_low;
    256 
    257 		bzsc_set_dma_tc(sc, 0);
    258 		break;
    259 	}
    260 
    261 	return(retval);
    262 }
    263 
    264 /* Check if address and len is ok for DMA transfer */
    265 int bzsc_need_bump(struct sfas_softc *sc, void *ptr, int len)
    266 {
    267 	int	p;
    268 
    269 	p = (int)p & 0x03;
    270 
    271 	if (p) {
    272 		p = 4-p;
    273 
    274 		if (len < 256)
    275 			p = len;
    276 	}
    277 
    278 	return(p);
    279 }
    280 
    281 /* Interrupt driven routines */
    282 int bzsc_build_dma_chain(struct sfas_softc *sc, struct sfas_dma_chain *chain,
    283 			   void *p, int l)
    284 {
    285 	int	n;
    286 
    287 	if (!l)
    288 		return(0);
    289 
    290 #define set_link(n, p, l, f)\
    291 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
    292 
    293 	n = 0;
    294 
    295 	if (l < 512)
    296 		set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
    297 	else if (
    298 #ifdef M68040
    299 		 (cpu040 && ((vm_offset_t)p >= 0xFFFC0000)) &&
    300 #endif
    301 		 ((vm_offset_t)p >= 0xFF000000)) {
    302 		int	len;
    303 
    304 		while(l) {
    305 			len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
    306 
    307 			set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
    308 
    309 			p += len;
    310 			l -= len;
    311 		}
    312 	} else  {
    313 		char		*ptr;
    314 		vm_offset_t	 pa, lastpa;
    315 		int		 len,  prelen,  postlen, max_t;
    316 
    317 		ptr = p;
    318 		len = l;
    319 
    320 		pa = kvtop(ptr);
    321 		prelen = ((int)ptr & 0x03);
    322 
    323 		if (prelen) {
    324 			prelen = 4-prelen;
    325 			set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
    326 			ptr += prelen;
    327 			len -= prelen;
    328 		}
    329 
    330 		lastpa = 0;
    331 		while(len > 3) {
    332 			pa = kvtop(ptr);
    333 			max_t = NBPG - (pa & PGOFSET);
    334 			if (max_t > len)
    335 				max_t = len;
    336 
    337 			max_t &= ~3;
    338 
    339 			if (lastpa == pa)
    340 				sc->sc_chain[n-1].len += max_t;
    341 			else
    342 				set_link(n, pa, max_t, SFAS_CHAIN_DMA);
    343 
    344 			lastpa = pa+max_t;
    345 
    346 			ptr += max_t;
    347 			len -= max_t;
    348 		}
    349 
    350 		if (len)
    351 			set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
    352 	}
    353 
    354 	return(n);
    355 }
    356 
    357 /* Turn on led */
    358 void bzsc_led_dummy(struct sfas_softc *sc)
    359 {
    360 }
    361