1 /* $NetBSD: rapide.c,v 1.33 2023/12/20 06:13:59 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1997-1998 Mark Brinicombe
5 * Copyright (c) 1997-1998 Causality Limited
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 Mark Brinicombe
18 * for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Card driver and probe and attach functions to use generic IDE driver
34 * for the RapIDE podule
35 */
36
37 /*
38 * Thanks to Chris Honey at Raymond Datalink for providing information on
39 * addressing the RapIDE podule.
40 * RapIDE32 is Copyright (C) 1995,1996 Raymond Datalink. RapIDE32 is
41 * manufactured under license by Yellowstone Educational Solutions.
42 */
43
44 /*
45 * At present this driver only supports the Issue 2 RapIDE podule.
46 */
47
48 /*
49 * A small amount of work is required for Issue 1 podule support.
50 * The primary differences are the register addresses.
51 * Things are eased by the fact that we can identify the card by register
52 * the same register on both issues of the podule.
53 * Once we kmnow the issue we must change all our addresses accordingly.
54 * All the control registers are mapped the same between cards.
55 * The interrupt handler needs to take note that the issue 1 card needs
56 * the interrupt to be cleared via the interrupt clear register.
57 * This means we share addresses for the mapping of the control block and
58 * thus the card driver does not need to know about the differences.
59 * The differences show up a the controller level.
60 * A structure is used to hold the information about the addressing etc.
61 * An array of these structures holds the information for the primary and
62 * secondary connectors. This needs to be extended to hold this information
63 * for both issues. Then the indexing of these structures will use the
64 * card version number.
65 *
66 * Opps just noticed a mistake. The interrupt request register is different
67 * between cards so the card level attach routine will need to consider this.
68 */
69
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: rapide.c,v 1.33 2023/12/20 06:13:59 thorpej Exp $");
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/conf.h>
76 #include <sys/device.h>
77 #include <sys/bus.h>
78
79 #include <machine/intr.h>
80 #include <machine/io.h>
81 #include <machine/bootconfig.h>
82 #include <arm/iomd/iomdreg.h>
83 #include <arm/iomd/iomdvar.h>
84 #include <acorn32/podulebus/podulebus.h>
85 #include <acorn32/podulebus/rapidereg.h>
86
87 #include <dev/ata/atavar.h>
88 #include <dev/ic/wdcreg.h>
89 #include <dev/ic/wdcvar.h>
90 #include <dev/podulebus/podules.h>
91
92
93 /*
94 * RapIDE podule device.
95 *
96 * This probes and attaches the top level RapIDE device to the podulebus.
97 * It then configures any children of the RapIDE device.
98 * The attach args specify whether it is configuring the primary or
99 * secondary channel.
100 * The children are expected to be wdc devices using rapide attachments.
101 */
102
103 /*
104 * RapIDE card softc structure.
105 *
106 * Contains the device node, podule information and global information
107 * required by the driver such as the card version and the interrupt mask.
108 */
109
110 struct rapide_softc {
111 struct wdc_softc sc_wdcdev; /* common wdc definitions */
112 struct ata_channel *sc_chanarray[2]; /* channels definition */
113 podule_t *sc_podule; /* Our podule info */
114 int sc_podule_number; /* Our podule number */
115 int sc_intr_enable_mask; /* Global intr mask */
116 int sc_version; /* Card version */
117 bus_space_tag_t sc_ctliot; /* Bus tag */
118 bus_space_handle_t sc_ctlioh; /* control handler */
119 struct rapide_channel {
120 struct ata_channel rc_channel; /* generic part */
121 irqhandler_t rc_ih; /* interrupt handler */
122 int rc_irqmask; /* IRQ mask for this channel */
123 } rapide_channels[2];
124 struct wdc_regs sc_wdc_regs[2];
125 };
126
127 int rapide_probe (device_t, struct cfdata *, void *);
128 void rapide_attach (device_t, device_t, void *);
129 void rapide_shutdown (void *arg);
130 int rapide_intr (void *);
131
132 CFATTACH_DECL_NEW(rapide, sizeof(struct rapide_softc),
133 rapide_probe, rapide_attach, NULL, NULL);
134
135 /*
136 * We have a private bus space tag.
137 * This is created by copying the podulebus tag and then replacing
138 * a couple of the transfer functions.
139 */
140
141 static struct bus_space rapide_bs_tag;
142
143 bs_rm_4_proto(rapide);
144 bs_wm_4_proto(rapide);
145
146 /*
147 * Create an array of address structures. These define the addresses and
148 * masks needed for the different channels for the card.
149 *
150 * XXX - Needs some work for issue 1 cards.
151 */
152
153 struct {
154 u_int registers;
155 u_int aux_register;
156 u_int data_register;
157 u_int irq_mask;
158 } rapide_info[] = {
159 { PRIMARY_DRIVE_REGISTERS_OFFSET, PRIMARY_AUX_REGISTER_OFFSET,
160 PRIMARY_DATA_REGISTER_OFFSET, PRIMARY_IRQ_MASK },
161 { SECONDARY_DRIVE_REGISTERS_OFFSET, SECONDARY_AUX_REGISTER_OFFSET,
162 SECONDARY_DATA_REGISTER_OFFSET, SECONDARY_IRQ_MASK }
163 };
164
165
166 /*
167 * Card probe function
168 *
169 * Just match the manufacturer and podule ID's
170 */
171
172 int
rapide_probe(device_t parent,cfdata_t cf,void * aux)173 rapide_probe(device_t parent, cfdata_t cf, void *aux)
174 {
175 struct podule_attach_args *pa = (void *)aux;
176
177 return (pa->pa_product == PODULE_RAPIDE);
178 }
179
180 /*
181 * Card attach function
182 *
183 * Identify the card version and configure any children.
184 * Install a shutdown handler to kill interrupts on shutdown
185 */
186
187 void
rapide_attach(device_t parent,device_t self,void * aux)188 rapide_attach(device_t parent, device_t self, void *aux)
189 {
190 struct rapide_softc *sc = device_private(self);
191 struct podule_attach_args *pa = (void *)aux;
192 bus_space_tag_t iot;
193 bus_space_handle_t ctlioh;
194 u_int iobase;
195 int channel, i;
196 struct rapide_channel *rcp;
197 struct ata_channel *cp;
198 struct wdc_regs *wdr;
199 irqhandler_t *ihp;
200
201 /* Note the podule number and validate */
202 if (pa->pa_podule_number == -1)
203 panic("Podule has disappeared !");
204
205 sc->sc_wdcdev.sc_atac.atac_dev = self;
206 sc->sc_podule_number = pa->pa_podule_number;
207 sc->sc_podule = pa->pa_podule;
208 podules[sc->sc_podule_number].attached = 1;
209
210 sc->sc_wdcdev.regs = sc->sc_wdc_regs;
211
212 set_easi_cycle_type(sc->sc_podule_number, EASI_CYCLE_TYPE_C);
213
214 /*
215 * Duplicate the podule bus space tag and provide alternative
216 * bus_space_read_multi_4() and bus_space_write_multi_4()
217 * functions.
218 */
219 rapide_bs_tag = *pa->pa_iot;
220 rapide_bs_tag.bs_rm_4 = rapide_bs_rm_4;
221 rapide_bs_tag.bs_wm_4 = rapide_bs_wm_4;
222 sc->sc_ctliot = iot = &rapide_bs_tag;
223
224 if (bus_space_map(iot, pa->pa_podule->easi_base +
225 CONTROL_REGISTERS_OFFSET, CONTROL_REGISTER_SPACE, 0, &ctlioh))
226 panic("%s: Cannot map control registers", device_xname(self));
227
228 sc->sc_ctlioh = ctlioh;
229 sc->sc_version = bus_space_read_1(iot, ctlioh, VERSION_REGISTER_OFFSET) & VERSION_REGISTER_MASK;
230 /* bus_space_unmap(iot, ctl_ioh, CONTROL_REGISTER_SPACE);*/
231
232 aprint_normal(": Issue %d\n", sc->sc_version + 1);
233 if (sc->sc_version != VERSION_2_ID)
234 return;
235
236 if (shutdownhook_establish(rapide_shutdown, (void *)sc) == NULL)
237 panic("%s: Cannot install shutdown handler", device_xname(self));
238
239 /* Set the interrupt info for this podule */
240 sc->sc_podule->irq_addr = pa->pa_podule->easi_base
241 + CONTROL_REGISTERS_OFFSET + IRQ_REQUEST_REGISTER_BYTE_OFFSET;
242 sc->sc_podule->irq_mask = IRQ_MASK;
243
244 iobase = pa->pa_podule->easi_base;
245
246 /* Fill in wdc and channel infos */
247 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA32;
248 sc->sc_wdcdev.sc_atac.atac_pio_cap = 0;
249 sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_chanarray;
250 sc->sc_wdcdev.sc_atac.atac_nchannels = 2;
251 sc->sc_wdcdev.wdc_maxdrives = 2;
252 for (channel = 0 ; channel < 2; channel++) {
253 rcp = &sc->rapide_channels[channel];
254 sc->sc_chanarray[channel] = &rcp->rc_channel;
255 cp = &rcp->rc_channel;
256 wdr = &sc->sc_wdc_regs[channel];
257
258 cp->ch_channel = channel;
259 cp->ch_atac = &sc->sc_wdcdev.sc_atac;
260 wdr->cmd_iot = iot;
261 wdr->ctl_iot = iot;
262 wdr->data32iot = iot;
263
264 if (bus_space_map(iot, iobase + rapide_info[channel].registers,
265 DRIVE_REGISTERS_SPACE, 0, &wdr->cmd_baseioh))
266 continue;
267 for (i = 0; i < WDC_NREG; i++) {
268 if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh,
269 i, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) {
270 bus_space_unmap(iot, wdr->cmd_baseioh,
271 DRIVE_REGISTERS_SPACE);
272 continue;
273 }
274 }
275 wdc_init_shadow_regs(wdr);
276 if (bus_space_map(iot, iobase +
277 rapide_info[channel].aux_register, 4, 0, &wdr->ctl_ioh)) {
278 bus_space_unmap(iot, wdr->cmd_baseioh,
279 DRIVE_REGISTERS_SPACE);
280 continue;
281 }
282 if (bus_space_map(iot, iobase +
283 rapide_info[channel].data_register, 4, 0, &wdr->data32ioh)) {
284 bus_space_unmap(iot, wdr->cmd_baseioh,
285 DRIVE_REGISTERS_SPACE);
286 bus_space_unmap(iot, wdr->ctl_ioh, 4);
287 continue;
288 }
289 /* Disable interrupts and clear any pending interrupts */
290 rcp->rc_irqmask = rapide_info[channel].irq_mask;
291 sc->sc_intr_enable_mask &= ~rcp->rc_irqmask;
292 bus_space_write_1(iot, sc->sc_ctlioh, IRQ_MASK_REGISTER_OFFSET,
293 sc->sc_intr_enable_mask);
294 /* XXX - Issue 1 cards will need to clear any pending interrupts */
295 ihp = &rcp->rc_ih;
296 ihp->ih_func = rapide_intr;
297 ihp->ih_arg = rcp;
298 ihp->ih_level = IPL_BIO;
299 ihp->ih_name = "rapide";
300 ihp->ih_maskaddr = pa->pa_podule->irq_addr;
301 ihp->ih_maskbits = rcp->rc_irqmask;
302 if (irq_claim(sc->sc_podule->interrupt, ihp))
303 panic("%s: Cannot claim interrupt %d",
304 device_xname(self), sc->sc_podule->interrupt);
305 /* clear any pending interrupts and enable interrupts */
306 sc->sc_intr_enable_mask |= rcp->rc_irqmask;
307 bus_space_write_1(iot, sc->sc_ctlioh,
308 IRQ_MASK_REGISTER_OFFSET, sc->sc_intr_enable_mask);
309 /* XXX - Issue 1 cards will need to clear any pending interrupts */
310 wdcattach(cp);
311 }
312 }
313
314 /*
315 * Card shutdown function
316 *
317 * Called via do_shutdown_hooks() during kernel shutdown.
318 * Clear the cards's interrupt mask to stop any podule interrupts.
319 */
320
321 void
rapide_shutdown(void * arg)322 rapide_shutdown(void *arg)
323 {
324 struct rapide_softc *sc = arg;
325
326 /* Disable card interrupts */
327 bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
328 IRQ_MASK_REGISTER_OFFSET, 0);
329 }
330
331 /*
332 * Podule interrupt handler
333 *
334 * If the interrupt was from our card pass it on to the wdc interrupt handler
335 */
336
337 int
rapide_intr(void * arg)338 rapide_intr(void *arg)
339 {
340 struct rapide_channel *rcp = arg;
341 irqhandler_t *ihp = &rcp->rc_ih;
342 volatile u_char *intraddr = (volatile u_char *)ihp->ih_maskaddr;
343
344 /* XXX - Issue 1 cards will need to clear the interrupt */
345
346 /* XXX - not bus space yet - should really be handled by podulebus */
347 if ((*intraddr) & ihp->ih_maskbits)
348 wdcintr(&rcp->rc_channel);
349
350 return(0);
351 }
352