1 /* $NetBSD: dma.c,v 1.1.1.1 1995/03/26 07:12:13 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 * dmagrab: ensure exclusive access to the DMA circuitry 46 * dmafree: free exclusive access to the DMA circuitry 47 * dmaint: DMA interrupt routine, switches to the current driver 48 * dmaaddr: specify 24 bit RAM address 49 * dmardat: set dma_mode and read word from dma_data 50 * dmawdat: set dma_mode and write word to dma_data 51 * dmacomm: like dmawdat, but first toggle WRBIT 52 * 53 * FIXME: The delay-loops should be done otherwise! 54 */ 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/kernel.h> 59 #include <machine/cpu.h> 60 #include <machine/iomap.h> 61 #include <machine/dma.h> 62 63 #define NDMA_DEV 10 /* Max 2 floppy's, 8 hard-disks */ 64 typedef struct { 65 int (*call_func)(); 66 int (*int_func)(); 67 void *softc; 68 } DMA_DISP; 69 70 static DMA_DISP dispatch[NDMA_DEV]; /* dispatch table */ 71 static int dma_free = 0; /* next free entry in dispatch table */ 72 static int dma_curr = 0; /* current entry in dispatch table */ 73 static int dmalock = 0; /* if != 0, dma is not free */ 74 static int (*xxxint)(); /* current interrupt function */ 75 static void *dma_softc; /* Device currently owning DMA-intr */ 76 static int sched_soft = 0; /* Software interrupt scheduled */ 77 78 static void cdmasoft __P((void)); 79 80 dmagrab(int_func, call_func, softc) 81 int (*int_func)(); 82 int (*call_func)(); 83 void *softc; 84 { 85 int sps; 86 DMA_DISP *disp; 87 88 sps = splbio(); 89 90 if(dmalock) { 91 disp = &dispatch[dma_free++]; 92 if(dma_free >= NDMA_DEV) 93 dma_free = 0; 94 if(disp->call_func != NULL) 95 panic("dma dispatch table overflow"); 96 disp->call_func = call_func; 97 disp->int_func = int_func; 98 disp->softc = softc; 99 splx(sps); 100 return; 101 } 102 dmalock++; 103 xxxint = int_func; /* Grab DMA interrupts */ 104 dma_softc = softc; /* Identify device which got DMA */ 105 (*call_func)(softc); /* Call followup function */ 106 splx(sps); 107 108 } 109 110 dmafree() 111 { 112 int sps; 113 DMA_DISP *disp; 114 115 sps = splbio(); 116 disp = &dispatch[dma_curr]; 117 if(disp->call_func != NULL) { 118 xxxint = disp->int_func; 119 dma_softc = disp->softc; 120 (*disp->call_func)(dma_softc); 121 disp->call_func = NULL; 122 if(++dma_curr >= NDMA_DEV) 123 dma_curr = 0; 124 splx(sps); 125 return; 126 } 127 dmalock = 0; 128 xxxint = NULL; /* no more DMA interrupts */ 129 splx(sps); 130 } 131 132 cdmaint(sr) 133 long sr; /* sr at time of interrupt */ 134 { 135 if(xxxint != NULL) { 136 if(!BASEPRI(sr)) { 137 if(!sched_soft++) 138 add_sicallback(cdmasoft, 0, 0); 139 } 140 else { 141 spl1(); 142 cdmasoft(); 143 } 144 } 145 else printf("DMA interrupt discarded\r\n"); 146 } 147 148 static void cdmasoft() 149 { 150 sched_soft = 0; 151 (*xxxint)(dma_softc); 152 } 153 154 dmaaddr(address) 155 caddr_t address; 156 { 157 register u_long ad = (u_long)address; 158 159 DMA->dma_addr[AD_LOW ] = (ad ) & 0xff; 160 DMA->dma_addr[AD_MID ] = (ad >> 8) & 0xff; 161 DMA->dma_addr[AD_HIGH] = (ad >>16) & 0xff; 162 } 163 164 int 165 dmardat(mode, delay) 166 int mode, delay; 167 { 168 while(--delay >= 0); 169 DMA->dma_mode = mode; 170 while(--delay >= 0); 171 return(DMA->dma_data); 172 } 173 174 dmawdat(mode, data, delay) 175 int mode, data, delay; 176 { 177 DMA->dma_mode = mode; 178 while(--delay >= 0); 179 DMA->dma_data = data; 180 while(--delay >= 0); 181 } 182 183 dmacomm(mode, data, delay) 184 int mode, data, delay; 185 { 186 DMA->dma_mode = mode; 187 DMA->dma_mode = mode ^ WRBIT; 188 DMA->dma_mode = mode; 189 while(--delay >= 0); 190 DMA->dma_data = data; 191 while(--delay >= 0); 192 } 193 194 int 195 dmastat(mode, delay) 196 int mode, delay; 197 { 198 while(--delay >= 0); 199 DMA->dma_mode = mode; 200 while(--delay >= 0); 201 return(DMA->dma_stat); 202 } 203