wdc_mb.c revision 1.1.2.2 1 /* $NetBSD: wdc_mb.c,v 1.1.2.2 1998/06/05 08:38:56 bouyer Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
5 *
6 * DMA and multi-sector PIO handling are derived from code contributed by
7 * Onno van der Linden.
8 *
9 * ISA attachment created by Christopher G. Demetriou.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Charles M. Hannum.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/device.h>
42
43 #include <machine/cpu.h>
44 #include <machine/bus.h>
45 #include <machine/iomap.h>
46 #include <machine/mfp.h>
47 #include <machine/dma.h>
48
49 #include <dev/ata/atavar.h>
50 #include <dev/ic/wdcvar.h>
51
52 #include <m68k/asm_single.h>
53
54 #include <atari/dev/ym2149reg.h>
55 #include <atari/atari/device.h>
56
57 /*
58 * XXX This code currently doesn't even try to allow 32-bit data port use.
59 */
60 static int claim_hw __P((void *, int));
61 static void free_hw __P((void *));
62
63 struct wdc_mb_softc {
64 struct wdc_softc sc_wdcdev;
65 struct channel_softc wdc_channel;
66 void *sc_ih;
67 };
68
69 int wdc_mb_probe __P((struct device *, struct cfdata *, void *));
70 void wdc_mb_attach __P((struct device *, struct device *, void *));
71
72 struct cfattach wdc_mb_ca = {
73 sizeof(struct wdc_mb_softc), wdc_mb_probe, wdc_mb_attach
74 };
75
76 int
77 wdc_mb_probe(parent, cfp, aux)
78 struct device *parent;
79 struct cfdata *cfp;
80 void *aux;
81 {
82 #if 0 /* XXX memset */
83 struct channel_softc ch = { 0 };
84 #else /* XXX memset */
85 struct channel_softc ch;
86 #endif /* XXX memset */
87 int result = 0;
88 u_char sv_ierb;
89
90 #if 0 /* XXX memset */
91 #else /* XXX memset */
92 bzero(&ch, sizeof ch);
93 #endif /* XXX memset */
94
95 if ((machineid & ATARI_TT) || strcmp("wdc", aux) || cfp->cf_unit != 0)
96 return 0;
97 if (!atari_realconfig)
98 return 0;
99
100 ch.cmd_iot = ch.ctl_iot = mb_alloc_bus_space_tag();
101 if (ch.cmd_iot == NULL)
102 return 0;
103 ch.cmd_iot->stride = 2;
104 ch.cmd_iot->wo_1 = 1;
105
106 if (bus_space_map(ch.cmd_iot, 0xfff00000, 0x40, 0, &ch.cmd_ioh))
107 return 0;
108 if (bus_space_subregion(ch.cmd_iot, ch.cmd_ioh, 0x38, 1, &ch.ctl_ioh))
109 return 0;
110
111 /*
112 * Make sure IDE interrupts are disabled during probing.
113 */
114 sv_ierb = MFP->mf_ierb;
115 MFP->mf_ierb &= ~IB_DINT;
116
117 /*
118 * Make sure that IDE is turned on on the Falcon.
119 */
120 if (machineid & ATARI_FALCON)
121 ym2149_ser2(0);
122
123 result = wdcprobe(&ch);
124
125 MFP->mf_ierb = sv_ierb;
126
127 bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, 0x40);
128 mb_free_bus_space_tag(ch.cmd_iot);
129
130 return (result);
131 }
132
133 void
134 wdc_mb_attach(parent, self, aux)
135 struct device *parent, *self;
136 void *aux;
137 {
138 struct wdc_mb_softc *sc = (void *)self;
139
140 printf("\n");
141
142 sc->wdc_channel.cmd_iot = sc->wdc_channel.ctl_iot =
143 mb_alloc_bus_space_tag();
144 sc->wdc_channel.cmd_iot->stride = 2;
145 sc->wdc_channel.cmd_iot->wo_1 = 1;
146 if (bus_space_map(sc->wdc_channel.cmd_iot, 0xfff00000, 0x40, 0,
147 &sc->wdc_channel.cmd_ioh)) {
148 printf("%s: couldn't map registers\n",
149 sc->sc_wdcdev.sc_dev.dv_xname);
150 return;
151 }
152 if (bus_space_subregion(sc->wdc_channel.cmd_iot,
153 sc->wdc_channel.cmd_ioh, 0x38, 1, &sc->wdc_channel.ctl_ioh))
154 return;
155
156 /*
157 * Play a nasty trick here. Normally we only manipulate the
158 * interrupt *mask*. However to defeat wd_get_parms(), we
159 * disable the interrupts here using the *enable* register.
160 */
161 MFP->mf_ierb &= ~IB_DINT;
162
163 sc->sc_wdcdev.cap |= WDC_CAPABILITY_HWLOCK;
164 sc->sc_wdcdev.pio_mode = 0;
165 sc->sc_wdcdev.claim_hw = &claim_hw;
166 sc->sc_wdcdev.free_hw = &free_hw;
167 sc->sc_wdcdev.channels = &sc->wdc_channel;
168 sc->sc_wdcdev.nchannels = 1;
169 sc->wdc_channel.channel = 0;
170 sc->wdc_channel.wdc = &sc->sc_wdcdev;
171 sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
172 M_DEVBUF, M_NOWAIT);
173 if (sc->wdc_channel.ch_queue == NULL) {
174 printf("%s: can't allocate memory for command queue",
175 sc->sc_wdcdev.sc_dev.dv_xname);
176 return;
177 }
178 wdcattach(&sc->wdc_channel);
179
180 /*
181 * Setup & enable disk related interrupts.
182 */
183 MFP->mf_ierb |= IB_DINT;
184 MFP->mf_iprb &= ~IB_DINT;
185 MFP->mf_imrb |= IB_DINT;
186 }
187
188 /*
189 * Hardware locking
190 */
191 static int wd_lock;
192
193 static int
194 claim_hw(softc, maysleep)
195 void *softc;
196 int maysleep;
197 {
198 if (wd_lock != DMA_LOCK_GRANT) {
199 if (wd_lock == DMA_LOCK_REQ) {
200 /*
201 * ST_DMA access is being claimed.
202 */
203 return 0;
204 }
205 if (!st_dmagrab((dma_farg)wdcintr,
206 (dma_farg)(maysleep ? NULL : wdcrestart), softc,
207 &wd_lock, 1))
208 return 0;
209 }
210 return 1;
211 }
212
213 static void
214 free_hw(softc)
215 void *softc;
216 {
217 /*
218 * Flush pending interrupts before giving-up lock
219 */
220 single_inst_bclr_b(MFP->mf_iprb, IB_DINT);
221
222 /*
223 * Only free the lock on a Falcon. On the Hades, keep it.
224 */
225 /* if (machineid & ATARI_FALCON) */
226 st_dmafree(softc, &wd_lock);
227 }
228