rside.c revision 1.1 1 /* $NetBSD: rside.c,v 1.1 2004/01/03 14:31:28 chris 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
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
39
40 #include <machine/intr.h>
41 #include <machine/io.h>
42 #include <machine/bus.h>
43 #include <acorn32/eb7500atx/rsidereg.h>
44 #include <machine/irqhandler.h>
45
46 #include <dev/ata/atavar.h>
47 #include <dev/ic/wdcvar.h>
48 #include <acorn32/eb7500atx/rsbus.h>
49
50 /*
51 * RiscStation IDE device.
52 *
53 * This probes and attaches the top level IDE device to the rsbus.
54 * It then configures any children of the IDE device.
55 * The attach args specify whether it is configuring the primary or
56 * secondary channel.
57 * The children are expected to be wdc devices using rside attachments.
58 *
59 * The hardware notes are:
60 * Two ide ports are fitted, each with registers spaced 0x40 bytes apart
61 * with the extra control register at offset 0x380 from the base of the
62 * port.
63 *
64 * Primary:
65 * Registers at 0x302b800 (nPCCS1 + 0x0)
66 * IRQ connected to nEvent1 (IRQ register D)
67 *
68 * Secondary:
69 * Registers at 0x302bc00 (nPCCS1 + 0x400)
70 * IRQ connected to nEvent2 (IRQ register D)
71 *
72 * PIO timings can be changed by modifying the access speed register in the
73 * IOMD, as there is nothing else in the nPCCS1 space.
74 *
75 * The Reset line is asserted by unsetting bit 4 in IO register
76 * IOMD + 0x121CC.
77 */
78
79 /*
80 * make a private tag so that we can use mainbus's map/unmap
81 */
82
83 static struct bus_space rside_bs_tag;
84
85 /*
86 * RiscStation IDE card softc structure.
87 *
88 * Contains the device node, podule information and global information
89 * required by the driver such as the card version and the interrupt mask.
90 */
91
92 struct rside_softc {
93 struct wdc_softc sc_wdcdev; /* common wdc definitions */
94 struct wdc_channel *wdc_chanarray[2]; /* channels definition */
95 struct rside_channel {
96 struct wdc_channel wdc_channel; /* generic part */
97 struct ata_queue wdc_chqueue; /* channel queue */
98 irqhandler_t *wdc_ih; /* interrupt handler */
99 } rside_channels[2];
100 };
101
102 int rside_probe __P((struct device *, struct cfdata *, void *));
103 void rside_attach __P((struct device *, struct device *, void *));
104
105 CFATTACH_DECL(rside, sizeof(struct rside_softc),
106 rside_probe, rside_attach, NULL, NULL);
107
108 /*
109 * Create an array of address structures. These define the addresses and
110 * masks needed for the different channels.
111 *
112 * index = channel
113 */
114
115 struct {
116 u_int drive_registers;
117 u_int aux_register;
118 } rside_info[] = {
119 { PRIMARY_DRIVE_REGISTERS_POFFSET, PRIMARY_AUX_REGISTER_POFFSET,
120 },
121 { SECONDARY_DRIVE_REGISTERS_POFFSET, SECONDARY_AUX_REGISTER_POFFSET,
122 }
123 };
124
125 /*
126 * Card probe function
127 */
128
129 int
130 rside_probe(parent, cf, aux)
131 struct device *parent;
132 struct cfdata *cf;
133 void *aux;
134 {
135 /* if we're including this, then for now assume it exists */
136 return 1;
137 }
138
139 /*
140 * Card attach function
141 *
142 * Identify the card version and configure any children.
143 */
144
145 void
146 rside_attach(parent, self, aux)
147 struct device *parent, *self;
148 void *aux;
149 {
150 struct rside_softc *sc = (void *)self;
151 struct rsbus_attach_args *rs = (void *)aux;
152 int channel, i;
153 struct rside_channel *scp;
154 struct wdc_channel *cp;
155
156 printf("\n");
157
158 /*
159 * we need our own bus tag as the register spacing
160 * is not the default.
161 *
162 * For the rsbus the bus tag cookie is the shift
163 * to apply to registers
164 * So duplicate the bus space tag and change the
165 * cookie.
166 */
167
168 rside_bs_tag = *rs->sa_iot;
169 rside_bs_tag.bs_cookie = (void *) DRIVE_REGISTER_SPACING_SHIFT;
170
171 /* Fill in wdc and channel infos */
172 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
173 sc->sc_wdcdev.PIO_cap = 0;
174 sc->sc_wdcdev.DMA_cap = 0;
175 sc->sc_wdcdev.UDMA_cap = 0;
176 sc->sc_wdcdev.channels = sc->wdc_chanarray;
177 sc->sc_wdcdev.nchannels = 2;
178 for (channel = 0 ; channel < 2; channel++) {
179 scp = &sc->rside_channels[channel];
180 sc->wdc_chanarray[channel] = &scp->wdc_channel;
181 cp = &scp->wdc_channel;
182
183 cp->channel = channel;
184 cp->wdc = &sc->sc_wdcdev;
185 cp->ch_queue = &scp->wdc_chqueue;
186 cp->cmd_iot = cp->ctl_iot = &rside_bs_tag;
187 if (bus_space_map(cp->cmd_iot,
188 rside_info[channel].drive_registers,
189 DRIVE_REGISTERS_SPACE, 0, &cp->cmd_baseioh))
190 panic("couldn't map drive registers channel = %d,"
191 "registers@0x08%x\n",
192 channel, rside_info[channel].drive_registers);
193
194 for (i = 0; i < WDC_NREG; i++) {
195 if (bus_space_subregion(cp->cmd_iot, cp->cmd_baseioh,
196 i * (DRIVE_REGISTER_BYTE_SPACING >> 2), 4,
197 &cp->cmd_iohs[i]) != 0) {
198 bus_space_unmap(cp->cmd_iot, cp->cmd_baseioh,
199 DRIVE_REGISTERS_SPACE);
200 continue;
201 }
202 }
203
204 if (bus_space_map(cp->ctl_iot,
205 rside_info[channel].aux_register, 0x4, 0, &cp->ctl_ioh))
206 {
207 bus_space_unmap(cp->cmd_iot, cp->cmd_baseioh,
208 DRIVE_REGISTERS_SPACE);
209 continue;
210 }
211
212
213 /* attach it to the interrupt */
214 if ((scp->wdc_ih = intr_claim((channel == 0 ? IRQ_NEVENT1 : IRQ_NEVENT2), IPL_BIO,
215 "rside", wdcintr, cp)) == NULL)
216 panic("%s: Cannot claim interrupt %d\n",
217 self->dv_xname, (channel == 0 ? IRQ_NEVENT1 : IRQ_NEVENT2));
218
219 wdcattach(cp);
220 }
221 }
222