Line data Source code
1 : /* $OpenBSD: wdc_isa.c,v 1.16 2017/09/08 05:36:52 deraadt Exp $ */
2 : /* $NetBSD: wdc_isa.c,v 1.15 1999/05/19 14:41:25 bouyer Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 : * All rights reserved.
7 : *
8 : * This code is derived from software contributed to The NetBSD Foundation
9 : * by Charles M. Hannum and by Onno van der Linden.
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 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 : * POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/systm.h>
35 : #include <sys/device.h>
36 : #include <sys/malloc.h>
37 :
38 : #include <machine/bus.h>
39 : #include <machine/intr.h>
40 :
41 : #include <dev/isa/isavar.h>
42 : #include <dev/isa/isadmavar.h>
43 :
44 : #include <dev/ata/atavar.h>
45 : #include <dev/ic/wdcvar.h>
46 :
47 : #include "isadma.h"
48 :
49 : #define WDC_ISA_REG_NPORTS 8
50 : #define WDC_ISA_AUXREG_OFFSET 0x206
51 : #define WDC_ISA_AUXREG_NPORTS 1 /* XXX "fdc" owns ports 0x3f7/0x377 */
52 :
53 : /* options passed via the 'flags' config keyword */
54 : #define WDC_OPTIONS_32 0x01 /* try to use 32bit data I/O */
55 :
56 : struct wdc_isa_softc {
57 : struct wdc_softc sc_wdcdev;
58 : struct channel_softc *wdc_chanptr;
59 : struct channel_softc wdc_channel;
60 : struct device *sc_isa;
61 : isa_chipset_tag_t sc_ic;
62 : void *sc_ih;
63 : int sc_drq;
64 : };
65 :
66 : int wdc_isa_probe(struct device *, void *, void *);
67 : void wdc_isa_attach(struct device *, struct device *, void *);
68 :
69 : struct cfattach wdc_isa_ca = {
70 : sizeof(struct wdc_isa_softc), wdc_isa_probe, wdc_isa_attach
71 : };
72 :
73 : #if NISADMA > 0
74 : static void wdc_isa_dma_setup(struct wdc_isa_softc *);
75 : static int wdc_isa_dma_init(void *, int, int, void *, size_t, int);
76 : static void wdc_isa_dma_start(void *, int, int);
77 : static int wdc_isa_dma_finish(void *, int, int, int);
78 : #endif /* NISADMA > 0 */
79 :
80 : int
81 0 : wdc_isa_probe(struct device *parent, void *match, void *aux)
82 : {
83 0 : struct channel_softc ch;
84 0 : struct isa_attach_args *ia = aux;
85 0 : struct cfdata *cf = ((struct device *)match)->dv_cfdata;
86 : int result = 0;
87 :
88 0 : bzero(&ch, sizeof ch);
89 0 : ch.cmd_iot = ia->ia_iot;
90 0 : if (bus_space_map(ch.cmd_iot, ia->ia_iobase, WDC_ISA_REG_NPORTS, 0,
91 0 : &ch.cmd_ioh))
92 : goto out;
93 :
94 0 : ch.ctl_iot = ia->ia_iot;
95 0 : if (bus_space_map(ch.ctl_iot, ia->ia_iobase + WDC_ISA_AUXREG_OFFSET,
96 0 : WDC_ISA_AUXREG_NPORTS, 0, &ch.ctl_ioh))
97 : goto outunmap;
98 :
99 0 : if (cf->cf_flags & WDC_OPTION_PROBE_VERBOSE)
100 0 : ch.ch_flags |= WDCF_VERBOSE_PROBE;
101 :
102 0 : result = wdcprobe(&ch);
103 0 : if (result) {
104 0 : ia->ia_iosize = WDC_ISA_REG_NPORTS;
105 0 : ia->ia_msize = 0;
106 0 : }
107 :
108 0 : bus_space_unmap(ch.ctl_iot, ch.ctl_ioh, WDC_ISA_AUXREG_NPORTS);
109 : outunmap:
110 0 : bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, WDC_ISA_REG_NPORTS);
111 : out:
112 0 : return (result);
113 0 : }
114 :
115 : void
116 0 : wdc_isa_attach(struct device *parent, struct device *self, void *aux)
117 : {
118 0 : struct wdc_isa_softc *sc = (void *)self;
119 0 : struct isa_attach_args *ia = aux;
120 :
121 0 : printf("\n");
122 :
123 0 : sc->wdc_channel.cmd_iot = ia->ia_iot;
124 0 : sc->wdc_channel.ctl_iot = ia->ia_iot;
125 0 : sc->sc_ic = ia->ia_ic;
126 0 : sc->sc_isa = parent;
127 :
128 0 : if (bus_space_map(sc->wdc_channel.cmd_iot, ia->ia_iobase,
129 0 : WDC_ISA_REG_NPORTS, 0, &sc->wdc_channel.cmd_ioh) ||
130 0 : bus_space_map(sc->wdc_channel.ctl_iot,
131 0 : ia->ia_iobase + WDC_ISA_AUXREG_OFFSET, WDC_ISA_AUXREG_NPORTS,
132 0 : 0, &sc->wdc_channel.ctl_ioh)) {
133 0 : printf("%s: couldn't map registers\n",
134 0 : sc->sc_wdcdev.sc_dev.dv_xname);
135 0 : }
136 0 : sc->wdc_channel.data32iot = sc->wdc_channel.cmd_iot;
137 0 : sc->wdc_channel.data32ioh = sc->wdc_channel.cmd_ioh;
138 :
139 0 : sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
140 0 : IPL_BIO, wdcintr, &sc->wdc_channel, sc->sc_wdcdev.sc_dev.dv_xname);
141 :
142 0 : if (ia->ia_drq != DRQUNK) {
143 : #if NISADMA > 0
144 0 : sc->sc_drq = ia->ia_drq;
145 :
146 0 : sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
147 0 : sc->sc_wdcdev.dma_arg = sc;
148 0 : sc->sc_wdcdev.dma_init = wdc_isa_dma_init;
149 0 : sc->sc_wdcdev.dma_start = wdc_isa_dma_start;
150 0 : sc->sc_wdcdev.dma_finish = wdc_isa_dma_finish;
151 0 : wdc_isa_dma_setup(sc);
152 : #else /* NISADMA > 0 */
153 : printf("%s: ignoring drq, isa dma not supported",
154 : sc->sc_wdcdev.sc_dev.dv_xname);
155 : #endif /* NISADMA > 0 */
156 0 : }
157 0 : sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_PREATA;
158 0 : if (sc->sc_wdcdev.sc_dev.dv_cfdata->cf_flags & WDC_OPTIONS_32)
159 0 : sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA32;
160 0 : sc->sc_wdcdev.PIO_cap = 0;
161 0 : sc->wdc_chanptr = &sc->wdc_channel;
162 0 : sc->sc_wdcdev.channels = &sc->wdc_chanptr;
163 0 : sc->sc_wdcdev.nchannels = 1;
164 0 : sc->wdc_channel.channel = 0;
165 0 : sc->wdc_channel.wdc = &sc->sc_wdcdev;
166 0 : sc->wdc_channel.ch_queue = wdc_alloc_queue();
167 0 : if (sc->wdc_channel.ch_queue == NULL) {
168 0 : printf("%s: cannot allocate channel queue",
169 : sc->sc_wdcdev.sc_dev.dv_xname);
170 0 : return;
171 : }
172 0 : wdcattach(&sc->wdc_channel);
173 0 : wdc_print_current_modes(&sc->wdc_channel);
174 0 : }
175 :
176 : #if NISADMA > 0
177 : static void
178 0 : wdc_isa_dma_setup(struct wdc_isa_softc *sc)
179 : {
180 0 : if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
181 : MAXPHYS, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
182 0 : printf("%s: can't create map for drq %d\n",
183 0 : sc->sc_wdcdev.sc_dev.dv_xname, sc->sc_drq);
184 0 : sc->sc_wdcdev.cap &= ~WDC_CAPABILITY_DMA;
185 0 : }
186 0 : }
187 :
188 : static int
189 0 : wdc_isa_dma_init(void *v, int channel, int drive, void *databuf, size_t datalen,
190 : int read)
191 : {
192 0 : struct wdc_isa_softc *sc = v;
193 :
194 0 : isa_dmastart(sc->sc_isa, sc->sc_drq, databuf, datalen, NULL,
195 0 : (read ? DMAMODE_READ : DMAMODE_WRITE),
196 : BUS_DMA_NOWAIT);
197 :
198 0 : return 0;
199 : }
200 :
201 : static void
202 0 : wdc_isa_dma_start(void *v, int channel, int drive)
203 : {
204 : /* nothing to do */
205 0 : }
206 :
207 : static int
208 0 : wdc_isa_dma_finish(void *v, int channel, int drive, int force)
209 : {
210 0 : struct wdc_isa_softc *sc = v;
211 :
212 0 : isa_dmadone(sc->sc_isa, sc->sc_drq);
213 :
214 0 : return 0;
215 : }
216 : #endif /* NISADMA > 0 */
|