ahsc.c revision 1.27.8.3 1 1.27.8.3 nathanw /* $NetBSD: ahsc.c,v 1.27.8.3 2002/10/18 02:34:44 nathanw Exp $ */
2 1.27.8.2 nathanw
3 1.27.8.2 nathanw /*
4 1.27.8.2 nathanw * Copyright (c) 1994 Christian E. Hopps
5 1.27.8.2 nathanw * Copyright (c) 1982, 1990 The Regents of the University of California.
6 1.27.8.2 nathanw * All rights reserved.
7 1.27.8.2 nathanw *
8 1.27.8.2 nathanw * Redistribution and use in source and binary forms, with or without
9 1.27.8.2 nathanw * modification, are permitted provided that the following conditions
10 1.27.8.2 nathanw * are met:
11 1.27.8.2 nathanw * 1. Redistributions of source code must retain the above copyright
12 1.27.8.2 nathanw * notice, this list of conditions and the following disclaimer.
13 1.27.8.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
14 1.27.8.2 nathanw * notice, this list of conditions and the following disclaimer in the
15 1.27.8.2 nathanw * documentation and/or other materials provided with the distribution.
16 1.27.8.2 nathanw * 3. All advertising materials mentioning features or use of this software
17 1.27.8.2 nathanw * must display the following acknowledgement:
18 1.27.8.2 nathanw * This product includes software developed by the University of
19 1.27.8.2 nathanw * California, Berkeley and its contributors.
20 1.27.8.2 nathanw * 4. Neither the name of the University nor the names of its contributors
21 1.27.8.2 nathanw * may be used to endorse or promote products derived from this software
22 1.27.8.2 nathanw * without specific prior written permission.
23 1.27.8.2 nathanw *
24 1.27.8.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 1.27.8.2 nathanw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 1.27.8.2 nathanw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 1.27.8.2 nathanw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 1.27.8.2 nathanw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 1.27.8.2 nathanw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 1.27.8.2 nathanw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 1.27.8.2 nathanw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 1.27.8.2 nathanw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 1.27.8.2 nathanw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 1.27.8.2 nathanw * SUCH DAMAGE.
35 1.27.8.2 nathanw *
36 1.27.8.2 nathanw * @(#)dma.c
37 1.27.8.2 nathanw */
38 1.27.8.2 nathanw
39 1.27.8.2 nathanw #include <sys/cdefs.h>
40 1.27.8.3 nathanw __KERNEL_RCSID(0, "$NetBSD: ahsc.c,v 1.27.8.3 2002/10/18 02:34:44 nathanw Exp $");
41 1.27.8.2 nathanw
42 1.27.8.2 nathanw #include <sys/param.h>
43 1.27.8.2 nathanw #include <sys/systm.h>
44 1.27.8.2 nathanw #include <sys/kernel.h>
45 1.27.8.2 nathanw #include <sys/device.h>
46 1.27.8.2 nathanw #include <dev/scsipi/scsi_all.h>
47 1.27.8.2 nathanw #include <dev/scsipi/scsipi_all.h>
48 1.27.8.2 nathanw #include <dev/scsipi/scsiconf.h>
49 1.27.8.2 nathanw #include <amiga/amiga/custom.h>
50 1.27.8.2 nathanw #include <amiga/amiga/cc.h>
51 1.27.8.2 nathanw #include <amiga/amiga/cfdev.h>
52 1.27.8.2 nathanw #include <amiga/amiga/device.h>
53 1.27.8.2 nathanw #include <amiga/amiga/isr.h>
54 1.27.8.2 nathanw #include <amiga/dev/dmavar.h>
55 1.27.8.2 nathanw #include <amiga/dev/sbicreg.h>
56 1.27.8.2 nathanw #include <amiga/dev/sbicvar.h>
57 1.27.8.2 nathanw #include <amiga/dev/ahscreg.h>
58 1.27.8.2 nathanw #include <amiga/dev/zbusvar.h>
59 1.27.8.2 nathanw
60 1.27.8.2 nathanw #include <machine/cpu.h>
61 1.27.8.2 nathanw
62 1.27.8.2 nathanw void ahscattach(struct device *, struct device *, void *);
63 1.27.8.2 nathanw int ahscmatch(struct device *, struct cfdata *, void *);
64 1.27.8.2 nathanw
65 1.27.8.2 nathanw void ahsc_enintr(struct sbic_softc *);
66 1.27.8.2 nathanw void ahsc_dmastop(struct sbic_softc *);
67 1.27.8.2 nathanw int ahsc_dmanext(struct sbic_softc *);
68 1.27.8.2 nathanw int ahsc_dmaintr(void *);
69 1.27.8.2 nathanw int ahsc_dmago(struct sbic_softc *, char *, int, int);
70 1.27.8.2 nathanw
71 1.27.8.2 nathanw #ifdef DEBUG
72 1.27.8.2 nathanw void ahsc_dump(void);
73 1.27.8.2 nathanw #endif
74 1.27.8.2 nathanw
75 1.27.8.2 nathanw #ifdef DEBUG
76 1.27.8.2 nathanw int ahsc_dmadebug = 0;
77 1.27.8.2 nathanw #endif
78 1.27.8.2 nathanw
79 1.27.8.3 nathanw CFATTACH_DECL(ahsc, sizeof(struct sbic_softc),
80 1.27.8.3 nathanw ahscmatch, ahscattach, NULL, NULL);
81 1.27.8.2 nathanw
82 1.27.8.2 nathanw /*
83 1.27.8.2 nathanw * if we are an A3000 we are here.
84 1.27.8.2 nathanw */
85 1.27.8.2 nathanw int
86 1.27.8.2 nathanw ahscmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
87 1.27.8.2 nathanw {
88 1.27.8.2 nathanw char *mbusstr;
89 1.27.8.2 nathanw
90 1.27.8.2 nathanw mbusstr = auxp;
91 1.27.8.2 nathanw if (is_a3000() && matchname(auxp, "ahsc"))
92 1.27.8.2 nathanw return(1);
93 1.27.8.2 nathanw return(0);
94 1.27.8.2 nathanw }
95 1.27.8.2 nathanw
96 1.27.8.2 nathanw void
97 1.27.8.2 nathanw ahscattach(struct device *pdp, struct device *dp, void *auxp)
98 1.27.8.2 nathanw {
99 1.27.8.2 nathanw volatile struct sdmac *rp;
100 1.27.8.2 nathanw struct sbic_softc *sc = (struct sbic_softc *)dp;
101 1.27.8.2 nathanw struct cfdev *cdp, *ecdp;
102 1.27.8.2 nathanw struct scsipi_adapter *adapt = &sc->sc_adapter;
103 1.27.8.2 nathanw struct scsipi_channel *chan = &sc->sc_channel;
104 1.27.8.2 nathanw
105 1.27.8.2 nathanw ecdp = &cfdev[ncfdev];
106 1.27.8.2 nathanw
107 1.27.8.2 nathanw for (cdp = cfdev; cdp < ecdp; cdp++) {
108 1.27.8.2 nathanw if (cdp->rom.manid == 8738 &&
109 1.27.8.2 nathanw cdp->rom.prodid == 35)
110 1.27.8.2 nathanw break;
111 1.27.8.2 nathanw }
112 1.27.8.2 nathanw
113 1.27.8.2 nathanw sc->sc_cregs = rp = ztwomap(0xdd0000);
114 1.27.8.2 nathanw /*
115 1.27.8.2 nathanw * disable ints and reset bank register
116 1.27.8.2 nathanw */
117 1.27.8.2 nathanw rp->CNTR = CNTR_PDMD;
118 1.27.8.2 nathanw rp->DAWR = DAWR_AHSC;
119 1.27.8.2 nathanw sc->sc_enintr = ahsc_enintr;
120 1.27.8.2 nathanw sc->sc_dmago = ahsc_dmago;
121 1.27.8.2 nathanw sc->sc_dmanext = ahsc_dmanext;
122 1.27.8.2 nathanw sc->sc_dmastop = ahsc_dmastop;
123 1.27.8.2 nathanw sc->sc_dmacmd = 0;
124 1.27.8.2 nathanw
125 1.27.8.2 nathanw /*
126 1.27.8.2 nathanw * eveything is a valid dma address
127 1.27.8.2 nathanw */
128 1.27.8.2 nathanw sc->sc_dmamask = 0;
129 1.27.8.2 nathanw
130 1.27.8.2 nathanw if (cdp < ecdp) {
131 1.27.8.2 nathanw sc->sc_sbic.sbic_asr_p = ((vu_char *)rp + 0x43);
132 1.27.8.2 nathanw sc->sc_sbic.sbic_value_p = ((vu_char *)rp + 0x47);
133 1.27.8.2 nathanw printf(": modified for Apollo cpu board\n");
134 1.27.8.2 nathanw } else {
135 1.27.8.2 nathanw sc->sc_sbic.sbic_asr_p = ((vu_char *)rp + 0x41);
136 1.27.8.2 nathanw sc->sc_sbic.sbic_value_p = ((vu_char *)rp + 0x43);
137 1.27.8.2 nathanw printf("\n");
138 1.27.8.2 nathanw }
139 1.27.8.2 nathanw
140 1.27.8.2 nathanw sc->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143;
141 1.27.8.2 nathanw
142 1.27.8.2 nathanw /*
143 1.27.8.2 nathanw * Fill in the scsipi_adapter.
144 1.27.8.2 nathanw */
145 1.27.8.2 nathanw memset(adapt, 0, sizeof(*adapt));
146 1.27.8.2 nathanw adapt->adapt_dev = &sc->sc_dev;
147 1.27.8.2 nathanw adapt->adapt_nchannels = 1;
148 1.27.8.2 nathanw adapt->adapt_openings = 7;
149 1.27.8.2 nathanw adapt->adapt_max_periph = 1;
150 1.27.8.2 nathanw adapt->adapt_request = sbic_scsipi_request;
151 1.27.8.2 nathanw adapt->adapt_minphys = sbic_minphys;
152 1.27.8.2 nathanw
153 1.27.8.2 nathanw /*
154 1.27.8.2 nathanw * Fill in the scsipi_channel.
155 1.27.8.2 nathanw */
156 1.27.8.2 nathanw memset(chan, 0, sizeof(*chan));
157 1.27.8.2 nathanw chan->chan_adapter = adapt;
158 1.27.8.2 nathanw chan->chan_bustype = &scsi_bustype;
159 1.27.8.2 nathanw chan->chan_channel = 0;
160 1.27.8.2 nathanw chan->chan_ntargets = 8;
161 1.27.8.2 nathanw chan->chan_nluns = 8;
162 1.27.8.2 nathanw chan->chan_id = 7;
163 1.27.8.2 nathanw
164 1.27.8.2 nathanw sbicinit(sc);
165 1.27.8.2 nathanw
166 1.27.8.2 nathanw sc->sc_isr.isr_intr = ahsc_dmaintr;
167 1.27.8.2 nathanw sc->sc_isr.isr_arg = sc;
168 1.27.8.2 nathanw sc->sc_isr.isr_ipl = 2;
169 1.27.8.2 nathanw add_isr (&sc->sc_isr);
170 1.27.8.2 nathanw
171 1.27.8.2 nathanw /*
172 1.27.8.2 nathanw * attach all scsi units on us
173 1.27.8.2 nathanw */
174 1.27.8.2 nathanw config_found(dp, chan, scsiprint);
175 1.27.8.2 nathanw }
176 1.27.8.2 nathanw
177 1.27.8.2 nathanw void
178 1.27.8.2 nathanw ahsc_enintr(struct sbic_softc *dev)
179 1.27.8.2 nathanw {
180 1.27.8.2 nathanw volatile struct sdmac *sdp;
181 1.27.8.2 nathanw
182 1.27.8.2 nathanw sdp = dev->sc_cregs;
183 1.27.8.2 nathanw
184 1.27.8.2 nathanw dev->sc_flags |= SBICF_INTR;
185 1.27.8.2 nathanw sdp->CNTR = CNTR_PDMD | CNTR_INTEN;
186 1.27.8.2 nathanw }
187 1.27.8.2 nathanw
188 1.27.8.2 nathanw int
189 1.27.8.2 nathanw ahsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags)
190 1.27.8.2 nathanw {
191 1.27.8.2 nathanw volatile struct sdmac *sdp;
192 1.27.8.2 nathanw
193 1.27.8.2 nathanw sdp = dev->sc_cregs;
194 1.27.8.2 nathanw /*
195 1.27.8.2 nathanw * Set up the command word based on flags
196 1.27.8.2 nathanw */
197 1.27.8.2 nathanw dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN;
198 1.27.8.2 nathanw if ((flags & DMAGO_READ) == 0)
199 1.27.8.2 nathanw dev->sc_dmacmd |= CNTR_DDIR;
200 1.27.8.2 nathanw #ifdef DEBUG
201 1.27.8.2 nathanw if (ahsc_dmadebug & DDB_IO)
202 1.27.8.2 nathanw printf("ahsc_dmago: cmd %x\n", dev->sc_dmacmd);
203 1.27.8.2 nathanw #endif
204 1.27.8.2 nathanw
205 1.27.8.2 nathanw dev->sc_flags |= SBICF_INTR;
206 1.27.8.2 nathanw sdp->CNTR = dev->sc_dmacmd;
207 1.27.8.2 nathanw sdp->ACR = (u_int) dev->sc_cur->dc_addr;
208 1.27.8.2 nathanw sdp->ST_DMA = 1;
209 1.27.8.2 nathanw
210 1.27.8.2 nathanw return(dev->sc_tcnt);
211 1.27.8.2 nathanw }
212 1.27.8.2 nathanw
213 1.27.8.2 nathanw void
214 1.27.8.2 nathanw ahsc_dmastop(struct sbic_softc *dev)
215 1.27.8.2 nathanw {
216 1.27.8.2 nathanw volatile struct sdmac *sdp;
217 1.27.8.2 nathanw int s;
218 1.27.8.2 nathanw
219 1.27.8.2 nathanw sdp = dev->sc_cregs;
220 1.27.8.2 nathanw
221 1.27.8.2 nathanw #ifdef DEBUG
222 1.27.8.2 nathanw if (ahsc_dmadebug & DDB_FOLLOW)
223 1.27.8.2 nathanw printf("ahsc_dmastop()\n");
224 1.27.8.2 nathanw #endif
225 1.27.8.2 nathanw if (dev->sc_dmacmd) {
226 1.27.8.2 nathanw s = splbio();
227 1.27.8.2 nathanw if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
228 1.27.8.2 nathanw /*
229 1.27.8.2 nathanw * only FLUSH if terminal count not enabled,
230 1.27.8.2 nathanw * and reading from peripheral
231 1.27.8.2 nathanw */
232 1.27.8.2 nathanw sdp->FLUSH = 1;
233 1.27.8.2 nathanw while ((sdp->ISTR & ISTR_FE_FLG) == 0)
234 1.27.8.2 nathanw ;
235 1.27.8.2 nathanw }
236 1.27.8.2 nathanw /*
237 1.27.8.2 nathanw * clear possible interrupt and stop dma
238 1.27.8.2 nathanw */
239 1.27.8.2 nathanw sdp->CINT = 1;
240 1.27.8.2 nathanw sdp->SP_DMA = 1;
241 1.27.8.2 nathanw dev->sc_dmacmd = 0;
242 1.27.8.2 nathanw splx(s);
243 1.27.8.2 nathanw }
244 1.27.8.2 nathanw }
245 1.27.8.2 nathanw
246 1.27.8.2 nathanw int
247 1.27.8.2 nathanw ahsc_dmaintr(void *arg)
248 1.27.8.2 nathanw {
249 1.27.8.2 nathanw struct sbic_softc *dev = arg;
250 1.27.8.2 nathanw volatile struct sdmac *sdp;
251 1.27.8.2 nathanw int stat, found;
252 1.27.8.2 nathanw
253 1.27.8.2 nathanw sdp = dev->sc_cregs;
254 1.27.8.2 nathanw stat = sdp->ISTR;
255 1.27.8.2 nathanw
256 1.27.8.2 nathanw if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0)
257 1.27.8.2 nathanw return (0);
258 1.27.8.2 nathanw
259 1.27.8.2 nathanw #ifdef DEBUG
260 1.27.8.2 nathanw if (ahsc_dmadebug & DDB_FOLLOW)
261 1.27.8.2 nathanw printf("%s: dmaintr 0x%x\n", dev->sc_dev.dv_xname, stat);
262 1.27.8.2 nathanw #endif
263 1.27.8.2 nathanw
264 1.27.8.2 nathanw /*
265 1.27.8.2 nathanw * both, SCSI and DMA interrupts arrive here. I chose
266 1.27.8.2 nathanw * arbitrarily that DMA interrupts should have higher
267 1.27.8.2 nathanw * precedence than SCSI interrupts.
268 1.27.8.2 nathanw */
269 1.27.8.2 nathanw found = 0;
270 1.27.8.2 nathanw if (stat & ISTR_E_INT) {
271 1.27.8.2 nathanw ++found;
272 1.27.8.2 nathanw
273 1.27.8.2 nathanw sdp->CINT = 1; /* clear possible interrupt */
274 1.27.8.2 nathanw
275 1.27.8.2 nathanw /*
276 1.27.8.2 nathanw * check for SCSI ints in the same go and
277 1.27.8.2 nathanw * eventually save an interrupt
278 1.27.8.2 nathanw */
279 1.27.8.2 nathanw }
280 1.27.8.2 nathanw
281 1.27.8.2 nathanw if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS)
282 1.27.8.2 nathanw found += sbicintr(dev);
283 1.27.8.2 nathanw return(found);
284 1.27.8.2 nathanw }
285 1.27.8.2 nathanw
286 1.27.8.2 nathanw
287 1.27.8.2 nathanw int
288 1.27.8.2 nathanw ahsc_dmanext(struct sbic_softc *dev)
289 1.27.8.2 nathanw {
290 1.27.8.2 nathanw volatile struct sdmac *sdp;
291 1.27.8.2 nathanw
292 1.27.8.2 nathanw sdp = dev->sc_cregs;
293 1.27.8.2 nathanw
294 1.27.8.2 nathanw if (dev->sc_cur > dev->sc_last) {
295 1.27.8.2 nathanw /* shouldn't happen !! */
296 1.27.8.2 nathanw printf("ahsc_dmanext at end !!!\n");
297 1.27.8.2 nathanw ahsc_dmastop(dev);
298 1.27.8.2 nathanw return(0);
299 1.27.8.2 nathanw }
300 1.27.8.2 nathanw if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
301 1.27.8.2 nathanw /*
302 1.27.8.2 nathanw * only FLUSH if terminal count not enabled,
303 1.27.8.2 nathanw * and reading from peripheral
304 1.27.8.2 nathanw */
305 1.27.8.2 nathanw sdp->FLUSH = 1;
306 1.27.8.2 nathanw while ((sdp->ISTR & ISTR_FE_FLG) == 0)
307 1.27.8.2 nathanw ;
308 1.27.8.2 nathanw }
309 1.27.8.2 nathanw /*
310 1.27.8.2 nathanw * clear possible interrupt and stop dma
311 1.27.8.2 nathanw */
312 1.27.8.2 nathanw sdp->CINT = 1; /* clear possible interrupt */
313 1.27.8.2 nathanw sdp->SP_DMA = 1; /* stop dma */
314 1.27.8.2 nathanw sdp->CNTR = dev->sc_dmacmd;
315 1.27.8.2 nathanw sdp->ACR = (u_int)dev->sc_cur->dc_addr;
316 1.27.8.2 nathanw sdp->ST_DMA = 1;
317 1.27.8.2 nathanw
318 1.27.8.2 nathanw dev->sc_tcnt = dev->sc_cur->dc_count << 1;
319 1.27.8.2 nathanw return(dev->sc_tcnt);
320 1.27.8.2 nathanw }
321 1.27.8.2 nathanw
322 1.27.8.2 nathanw #ifdef DEBUG
323 1.27.8.2 nathanw void
324 1.27.8.2 nathanw ahsc_dump(void)
325 1.27.8.2 nathanw {
326 1.27.8.2 nathanw extern struct cfdriver ahsc_cd;
327 1.27.8.2 nathanw int i;
328 1.27.8.2 nathanw
329 1.27.8.2 nathanw for (i = 0; i < ahsc_cd.cd_ndevs; ++i)
330 1.27.8.2 nathanw if (ahsc_cd.cd_devs[i])
331 1.27.8.2 nathanw sbic_dump(ahsc_cd.cd_devs[i]);
332 1.27.8.2 nathanw }
333 1.27.8.2 nathanw #endif
334