1 /* $NetBSD: wdc_buddha.c,v 1.3 2008/03/18 20:46:35 cube Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Michael L. Hitch and Ignatios Souvatzis.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/device.h>
38 #include <machine/cpu.h>
39 #include <machine/bus.h>
40 #include <machine/intr.h>
41 #include <machine/bswap.h>
43 #include <amiga/amiga/cia.h>
44 #include <amiga/amiga/custom.h>
45 #include <amiga/amiga/device.h>
46 #include <amiga/dev/zbusvar.h>
48 #include <dev/ata/atavar.h>
49 #include <dev/ic/wdcvar.h>
51 #define BUDDHA_MAX_CHANNELS 3
53 struct wdc_buddha_softc
{
54 struct wdc_softc sc_wdcdev
;
55 struct ata_channel
*wdc_chanarray
[BUDDHA_MAX_CHANNELS
];
56 struct ata_channel channels
[BUDDHA_MAX_CHANNELS
];
57 struct bus_space_tag sc_iot
;
62 int wdc_buddha_probe(device_t
, cfdata_t
, void *);
63 void wdc_buddha_attach(device_t
, device_t
, void *);
64 int wdc_buddha_intr(void *);
66 CFATTACH_DECL_NEW(wdc_buddha
, sizeof(struct wdc_buddha_softc
),
67 wdc_buddha_probe
, wdc_buddha_attach
, NULL
, NULL
);
70 wdc_buddha_probe(device_t parent
, cfdata_t cfp
, void *aux
)
72 struct zbus_args
*zap
;
76 if (zap
->manid
!= 4626)
79 if ((zap
->prodid
!= 0) && /* Buddha */
80 (zap
->prodid
!= 42)) /* Catweasel */
87 wdc_buddha_attach(device_t parent
, device_t self
, void *aux
)
89 struct wdc_buddha_softc
*sc
;
90 struct zbus_args
*zap
;
94 sc
= device_private(self
);
95 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
100 sc
->sc_iot
.base
= (bus_addr_t
)sc
->ba
;
101 sc
->sc_iot
.absm
= &amiga_bus_stride_4swap
;
104 if (zap
->prodid
== 42) {
105 aprint_normal(": Catweasel Z2\n");
107 } else if (zap
->serno
== 0)
108 aprint_normal(": Buddha\n");
110 aprint_normal(": Buddha Flash\n");
112 /* XXX pio mode setting not implemented yet. */
113 sc
->sc_wdcdev
.sc_atac
.atac_cap
= ATAC_CAP_DATA16
;
114 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 0;
115 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
116 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= nchannels
;
118 wdc_allocate_regs(&sc
->sc_wdcdev
);
120 for (ch
= 0; ch
< nchannels
; ch
++) {
121 struct ata_channel
*cp
;
122 struct wdc_regs
*wdr
;
125 cp
= &sc
->channels
[ch
];
126 sc
->wdc_chanarray
[ch
] = cp
;
129 cp
->ch_atac
= &sc
->sc_wdcdev
.sc_atac
;
131 malloc(sizeof(struct ata_queue
), M_DEVBUF
, M_NOWAIT
);
132 if (cp
->ch_queue
== NULL
) {
133 aprint_error_dev(self
,
134 "can't allocate memory for command queue\n");
140 * XXX According to the Buddha docs, we should use a method
141 * array that adds 0x40 to the address for byte accesses, to
142 * get the slow timing for command accesses, and the 0x00
143 * offset for the word (fast) accesses. This will be
144 * reconsidered when implementing setting the timing.
146 * XXX We also could consider to abuse the 32bit capability, or
147 * 32bit accesses to the words (which will read in two words)
148 * for better performance.
151 wdr
= CHAN_TO_WDC_REGS(cp
);
153 wdr
->cmd_iot
= &sc
->sc_iot
;
154 if (bus_space_map(wdr
->cmd_iot
, 0x210+ch
*0x80, 8, 0,
155 &wdr
->cmd_baseioh
)) {
156 aprint_error_dev(self
, "couldn't map cmd registers\n");
160 wdr
->ctl_iot
= &sc
->sc_iot
;
161 if (bus_space_map(wdr
->ctl_iot
, 0x250+ch
*0x80, 2, 0,
163 bus_space_unmap(wdr
->cmd_iot
, wdr
->cmd_baseioh
, 8);
164 aprint_error_dev(self
, "couldn't map ctl registers\n");
168 for (i
= 0; i
< WDC_NREG
; i
++) {
169 if (bus_space_subregion(wdr
->cmd_iot
, wdr
->cmd_baseioh
,
170 i
, i
== 0 ? 4 : 1, &wdr
->cmd_iohs
[i
]) != 0) {
171 aprint_error_dev(self
,
172 "couldn't subregion cmd regs\n");
177 wdc_init_shadow_regs(cp
);
181 sc
->sc_isr
.isr_intr
= wdc_buddha_intr
;
182 sc
->sc_isr
.isr_arg
= sc
;
183 sc
->sc_isr
.isr_ipl
= 2;
184 add_isr (&sc
->sc_isr
);
185 sc
->ba
[0xfc0] = 0; /* enable interrupts */
189 wdc_buddha_intr(void *arg
)
191 struct wdc_buddha_softc
*sc
= (struct wdc_buddha_softc
*)arg
;
192 int nchannels
, i
, ret
;
196 nchannels
= sc
->sc_wdcdev
.sc_atac
.atac_nchannels
;
199 for (i
=0; i
<nchannels
; i
++) {
200 if (p
[0xf00 + 0x40*i
] & 0x80) {
201 wdcintr(&sc
->channels
[i
]);