Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / acorn32 / podulebus / rapide.c
blobf181079f00aeaf8828d224522fa02552f5081e9d
1 /* $NetBSD: rapide.c,v 1.25 2006/10/09 21:12:44 bjh21 Exp $ */
3 /*
4 * Copyright (c) 1997-1998 Mark Brinicombe
5 * Copyright (c) 1997-1998 Causality Limited
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.
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.
33 * Card driver and probe and attach functions to use generic IDE driver
34 * for the RapIDE podule
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.
45 * At present this driver only supports the Issue 2 RapIDE podule.
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.
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.
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: rapide.c,v 1.25 2006/10/09 21:12:44 bjh21 Exp $");
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/conf.h>
76 #include <sys/device.h>
77 #include <sys/malloc.h>
79 #include <machine/intr.h>
80 #include <machine/io.h>
81 #include <machine/bus.h>
82 #include <machine/bootconfig.h>
83 #include <arm/iomd/iomdreg.h>
84 #include <arm/iomd/iomdvar.h>
85 #include <acorn32/podulebus/podulebus.h>
86 #include <acorn32/podulebus/rapidereg.h>
88 #include <dev/ata/atavar.h>
89 #include <dev/ic/wdcreg.h>
90 #include <dev/ic/wdcvar.h>
91 #include <dev/podulebus/podules.h>
95 * RapIDE podule device.
97 * This probes and attaches the top level RapIDE device to the podulebus.
98 * It then configures any children of the RapIDE device.
99 * The attach args specify whether it is configuring the primary or
100 * secondary channel.
101 * The children are expected to be wdc devices using rapide attachments.
105 * RapIDE card softc structure.
107 * Contains the device node, podule information and global information
108 * required by the driver such as the card version and the interrupt mask.
111 struct rapide_softc {
112 struct wdc_softc sc_wdcdev; /* common wdc definitions */
113 struct ata_channel *sc_chanarray[2]; /* channels definition */
114 podule_t *sc_podule; /* Our podule info */
115 int sc_podule_number; /* Our podule number */
116 int sc_intr_enable_mask; /* Global intr mask */
117 int sc_version; /* Card version */
118 bus_space_tag_t sc_ctliot; /* Bus tag */
119 bus_space_handle_t sc_ctlioh; /* control handler */
120 struct rapide_channel {
121 struct ata_channel rc_channel; /* generic part */
122 struct ata_queue rc_chqueue; /* channel queue */
123 irqhandler_t rc_ih; /* interrupt handler */
124 int rc_irqmask; /* IRQ mask for this channel */
125 } rapide_channels[2];
126 struct wdc_regs sc_wdc_regs[2];
129 int rapide_probe (device_t, struct cfdata *, void *);
130 void rapide_attach (device_t, device_t, void *);
131 void rapide_shutdown (void *arg);
132 int rapide_intr (void *);
134 CFATTACH_DECL_NEW(rapide, sizeof(struct rapide_softc),
135 rapide_probe, rapide_attach, NULL, NULL);
138 * We have a private bus space tag.
139 * This is created by copying the podulebus tag and then replacing
140 * a couple of the transfer functions.
143 static struct bus_space rapide_bs_tag;
145 bs_rm_4_proto(rapide);
146 bs_wm_4_proto(rapide);
149 * Create an array of address structures. These define the addresses and
150 * masks needed for the different channels for the card.
152 * XXX - Needs some work for issue 1 cards.
155 struct {
156 u_int registers;
157 u_int aux_register;
158 u_int data_register;
159 u_int irq_mask;
160 } rapide_info[] = {
161 { PRIMARY_DRIVE_REGISTERS_OFFSET, PRIMARY_AUX_REGISTER_OFFSET,
162 PRIMARY_DATA_REGISTER_OFFSET, PRIMARY_IRQ_MASK },
163 { SECONDARY_DRIVE_REGISTERS_OFFSET, SECONDARY_AUX_REGISTER_OFFSET,
164 SECONDARY_DATA_REGISTER_OFFSET, SECONDARY_IRQ_MASK }
169 * Card probe function
171 * Just match the manufacturer and podule ID's
175 rapide_probe(device_t parent, cfdata_t cf, void *aux)
177 struct podule_attach_args *pa = (void *)aux;
179 return (pa->pa_product == PODULE_RAPIDE);
183 * Card attach function
185 * Identify the card version and configure any children.
186 * Install a shutdown handler to kill interrupts on shutdown
189 void
190 rapide_attach(device_t parent, device_t self, void *aux)
192 struct rapide_softc *sc = device_private(self);
193 struct podule_attach_args *pa = (void *)aux;
194 bus_space_tag_t iot;
195 bus_space_handle_t ctlioh;
196 u_int iobase;
197 int channel, i;
198 struct rapide_channel *rcp;
199 struct ata_channel *cp;
200 struct wdc_regs *wdr;
201 irqhandler_t *ihp;
203 /* Note the podule number and validate */
204 if (pa->pa_podule_number == -1)
205 panic("Podule has disappeared !");
207 sc->sc_wdcdev.sc_atac.atac_dev = self;
208 sc->sc_podule_number = pa->pa_podule_number;
209 sc->sc_podule = pa->pa_podule;
210 podules[sc->sc_podule_number].attached = 1;
212 sc->sc_wdcdev.regs = sc->sc_wdc_regs;
214 set_easi_cycle_type(sc->sc_podule_number, EASI_CYCLE_TYPE_C);
217 * Duplicate the podule bus space tag and provide alternative
218 * bus_space_read_multi_4() and bus_space_write_multi_4()
219 * functions.
221 rapide_bs_tag = *pa->pa_iot;
222 rapide_bs_tag.bs_rm_4 = rapide_bs_rm_4;
223 rapide_bs_tag.bs_wm_4 = rapide_bs_wm_4;
224 sc->sc_ctliot = iot = &rapide_bs_tag;
226 if (bus_space_map(iot, pa->pa_podule->easi_base +
227 CONTROL_REGISTERS_OFFSET, CONTROL_REGISTER_SPACE, 0, &ctlioh))
228 panic("%s: Cannot map control registers", device_xname(self));
230 sc->sc_ctlioh = ctlioh;
231 sc->sc_version = bus_space_read_1(iot, ctlioh, VERSION_REGISTER_OFFSET) & VERSION_REGISTER_MASK;
232 /* bus_space_unmap(iot, ctl_ioh, CONTROL_REGISTER_SPACE);*/
234 aprint_normal(": Issue %d\n", sc->sc_version + 1);
235 if (sc->sc_version != VERSION_2_ID)
236 return;
238 if (shutdownhook_establish(rapide_shutdown, (void *)sc) == NULL)
239 panic("%s: Cannot install shutdown handler", device_xname(self));
241 /* Set the interrupt info for this podule */
242 sc->sc_podule->irq_addr = pa->pa_podule->easi_base
243 + CONTROL_REGISTERS_OFFSET + IRQ_REQUEST_REGISTER_BYTE_OFFSET;
244 sc->sc_podule->irq_mask = IRQ_MASK;
246 iobase = pa->pa_podule->easi_base;
248 /* Fill in wdc and channel infos */
249 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA32;
250 sc->sc_wdcdev.sc_atac.atac_pio_cap = 0;
251 sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_chanarray;
252 sc->sc_wdcdev.sc_atac.atac_nchannels = 2;
253 for (channel = 0 ; channel < 2; channel++) {
254 rcp = &sc->rapide_channels[channel];
255 sc->sc_chanarray[channel] = &rcp->rc_channel;
256 cp = &rcp->rc_channel;
257 wdr = &sc->sc_wdc_regs[channel];
259 cp->ch_channel = channel;
260 cp->ch_atac = &sc->sc_wdcdev.sc_atac;
261 cp->ch_queue = &rcp->rc_chqueue;
262 cp->ch_ndrive = 2;
263 wdr->cmd_iot = iot;
264 wdr->ctl_iot = iot;
265 wdr->data32iot = iot;
267 if (bus_space_map(iot, iobase + rapide_info[channel].registers,
268 DRIVE_REGISTERS_SPACE, 0, &wdr->cmd_baseioh))
269 continue;
270 for (i = 0; i < WDC_NREG; i++) {
271 if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh,
272 i, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) {
273 bus_space_unmap(iot, wdr->cmd_baseioh,
274 DRIVE_REGISTERS_SPACE);
275 continue;
278 wdc_init_shadow_regs(cp);
279 if (bus_space_map(iot, iobase +
280 rapide_info[channel].aux_register, 4, 0, &wdr->ctl_ioh)) {
281 bus_space_unmap(iot, wdr->cmd_baseioh,
282 DRIVE_REGISTERS_SPACE);
283 continue;
285 if (bus_space_map(iot, iobase +
286 rapide_info[channel].data_register, 4, 0, &wdr->data32ioh)) {
287 bus_space_unmap(iot, wdr->cmd_baseioh,
288 DRIVE_REGISTERS_SPACE);
289 bus_space_unmap(iot, wdr->ctl_ioh, 4);
290 continue;
292 /* Disable interrupts and clear any pending interrupts */
293 rcp->rc_irqmask = rapide_info[channel].irq_mask;
294 sc->sc_intr_enable_mask &= ~rcp->rc_irqmask;
295 bus_space_write_1(iot, sc->sc_ctlioh, IRQ_MASK_REGISTER_OFFSET,
296 sc->sc_intr_enable_mask);
297 /* XXX - Issue 1 cards will need to clear any pending interrupts */
298 ihp = &rcp->rc_ih;
299 ihp->ih_func = rapide_intr;
300 ihp->ih_arg = rcp;
301 ihp->ih_level = IPL_BIO;
302 ihp->ih_name = "rapide";
303 ihp->ih_maskaddr = pa->pa_podule->irq_addr;
304 ihp->ih_maskbits = rcp->rc_irqmask;
305 if (irq_claim(sc->sc_podule->interrupt, ihp))
306 panic("%s: Cannot claim interrupt %d",
307 device_xname(self), sc->sc_podule->interrupt);
308 /* clear any pending interrupts and enable interrupts */
309 sc->sc_intr_enable_mask |= rcp->rc_irqmask;
310 bus_space_write_1(iot, sc->sc_ctlioh,
311 IRQ_MASK_REGISTER_OFFSET, sc->sc_intr_enable_mask);
312 /* XXX - Issue 1 cards will need to clear any pending interrupts */
313 wdcattach(cp);
318 * Card shutdown function
320 * Called via do_shutdown_hooks() during kernel shutdown.
321 * Clear the cards's interrupt mask to stop any podule interrupts.
324 void
325 rapide_shutdown(void *arg)
327 struct rapide_softc *sc = arg;
329 /* Disable card interrupts */
330 bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
331 IRQ_MASK_REGISTER_OFFSET, 0);
335 * Podule interrupt handler
337 * If the interrupt was from our card pass it on to the wdc interrupt handler
341 rapide_intr(void *arg)
343 struct rapide_channel *rcp = arg;
344 irqhandler_t *ihp = &rcp->rc_ih;
345 volatile u_char *intraddr = (volatile u_char *)ihp->ih_maskaddr;
347 /* XXX - Issue 1 cards will need to clear the interrupt */
349 /* XXX - not bus space yet - should really be handled by podulebus */
350 if ((*intraddr) & ihp->ih_maskbits)
351 wdcintr(&rcp->rc_channel);
353 return(0);