Home | History | Annotate | Line # | Download | only in dev
dma.c revision 1.2
      1 /*	$NetBSD: dma.c,v 1.2 1995/04/22 22:18:17 leo Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Leo Weppelman.
      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 Leo Weppelman.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * This file contains special code dealing with the DMA interface
     35  * on the Atari ST.
     36  *
     37  * The DMA circuitry requires some special treatment for the peripheral
     38  * devices which make use of the ST's DMA feature (the hard disk and the
     39  * floppy drive).
     40  * All devices using DMA need mutually exclusive access and can follow some
     41  * standard pattern which will be provided in this file.
     42  *
     43  * The file contains the following entry points:
     44  *
     45  *	st_dmagrab:	ensure exclusive access to the DMA circuitry
     46  *	st_dmafree:	free exclusive access to the DMA circuitry
     47  *	st_dmawanted:	somebody is queued waiting for DMA-access
     48  *	dmaint:		DMA interrupt routine, switches to the current driver
     49  *	st_dmaaddr:	specify 24 bit RAM address
     50  *	st_dmacomm:	program DMA, flush FIFO first
     51  */
     52 
     53 #include <sys/param.h>
     54 #include <sys/systm.h>
     55 #include <sys/kernel.h>
     56 #include <machine/cpu.h>
     57 #include <machine/iomap.h>
     58 #include <machine/dma.h>
     59 
     60 #define	NDMA_DEV	10	/* Max 2 floppy's, 8 hard-disks		*/
     61 typedef struct {
     62 	void	(*call_func)();
     63 	void	(*int_func)();
     64 	void	*softc;
     65 } DMA_DISP;
     66 
     67 static	DMA_DISP  dispatch[NDMA_DEV];	/* dispatch table		     */
     68 static	int	  dma_free = 0;		/* next free entry in dispatch table */
     69 static	int	  dma_curr = 0;		/* current entry in dispatch table   */
     70 static	int	  dmalock = 0;		/* if != 0, dma is not free	     */
     71 static	void	  (*xxxint)();		/* current interrupt function	     */
     72 static	void	  *dma_softc;		/* Device currently owning DMA-intr  */
     73 static	int	  sched_soft = 0;	/* Software interrupt scheduled	     */
     74 
     75 static	void	cdmasoft __P((void));
     76 
     77 int st_dmagrab(int_func, call_func, softc, rcaller)
     78 void 	(*int_func)();
     79 void 	(*call_func)();
     80 void	*softc;
     81 int	rcaller;
     82 {
     83 	int		sps;
     84 	DMA_DISP	*disp;
     85 
     86 	sps = splbio();
     87 
     88 	if(dmalock) {
     89 		disp = &dispatch[dma_free++];
     90 		if(dma_free >= NDMA_DEV)
     91 			dma_free = 0;
     92 		if(disp->call_func != NULL)
     93 			panic("dma dispatch table overflow");
     94 		disp->call_func = call_func;
     95 		disp->int_func  = int_func;
     96 		disp->softc     = softc;
     97 		splx(sps);
     98 		return(0);
     99 	}
    100 	dmalock++;
    101 	xxxint    = int_func;	/* Grab DMA interrupts			*/
    102 	dma_softc = softc;	/* Identify device which got DMA	*/
    103 	if(rcaller) {
    104 		/*
    105 		 * Just return to caller immediately without going
    106 		 * through 'call_func' first.
    107 		 */
    108 		return(1);
    109 	}
    110 
    111 	(*call_func)(softc);	/* Call followup function		*/
    112 	splx(sps);
    113 	return(0);
    114 }
    115 
    116 void
    117 st_dmafree()
    118 {
    119 	int		sps;
    120 	DMA_DISP	*disp;
    121 
    122 	sps = splbio();
    123 	disp = &dispatch[dma_curr];
    124 	if(disp->call_func != NULL) {
    125 		xxxint    = disp->int_func;
    126 		dma_softc = disp->softc;
    127 		(*disp->call_func)(dma_softc);
    128 		disp->call_func = NULL;
    129 		if(++dma_curr >= NDMA_DEV)
    130 			dma_curr = 0;
    131 		splx(sps);
    132 		return;
    133 	}
    134 	dmalock = 0;
    135 	xxxint = NULL;		/* no more DMA interrupts */
    136 	splx(sps);
    137 }
    138 
    139 int
    140 st_dmawanted()
    141 {
    142 	return(dispatch[dma_curr].call_func != NULL);
    143 }
    144 
    145 cdmaint(sr)
    146 long	sr;	/* sr at time of interrupt */
    147 {
    148 	if(xxxint != NULL) {
    149 		if(!BASEPRI(sr)) {
    150 			if(!sched_soft++)
    151 				add_sicallback(cdmasoft, 0, 0);
    152 		}
    153 		else {
    154 			spl1();
    155 			cdmasoft();
    156 		}
    157 	}
    158 	else printf("DMA interrupt discarded\r\n");
    159 }
    160 
    161 static void cdmasoft()
    162 {
    163 	sched_soft = 0;
    164 	(*xxxint)(dma_softc);
    165 }
    166 
    167 /*
    168  * Setup address for DMA-transfer.
    169  * Note: The order _is_ important!
    170  */
    171 void
    172 st_dmaaddr(address)
    173 caddr_t	address;
    174 {
    175 	register u_long ad = (u_long)address;
    176 
    177 	DMA->dma_addr[AD_LOW ] = (ad     ) & 0xff;
    178 	DMA->dma_addr[AD_MID ] = (ad >> 8) & 0xff;
    179 	DMA->dma_addr[AD_HIGH] = (ad >>16) & 0xff;
    180 }
    181 
    182 /*
    183  * Program the DMA-controller to transfer 'nblk' blocks of 512 bytes.
    184  * The DMA_WRBIT trick flushes the FIFO before doing DMA.
    185  */
    186 void
    187 st_dmacomm(mode, data)
    188 int	mode, data;
    189 {
    190 	DMA->dma_mode = mode;
    191 	DMA->dma_mode = mode ^ DMA_WRBIT;
    192 	DMA->dma_mode = mode;
    193 	DMA->dma_data = data;
    194 }
    195