esp_mca.c revision 1.1 1 /* $NetBSD: esp_mca.c,v 1.1 2001/12/01 10:42:38 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum, Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center and Jaromir Dolecek.
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 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1994 Peter Galbavy
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by Peter Galbavy
55 * 4. The name of the author may not be used to endorse or promote products
56 * derived from this software without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
60 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
62 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
63 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
64 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
66 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
67 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 * POSSIBILITY OF SUCH DAMAGE.
69 */
70
71 /*
72 * Based on aic6360 by Jarle Greipsland
73 *
74 * Acknowledgements: Many of the algorithms used in this driver are
75 * inspired by the work of Julian Elischer (julian (at) tfs.com) and
76 * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu). Thanks a million!
77 */
78
79 /*
80 * Grabbed from the sparc port at revision 1.73 for the NeXT.
81 * Darrin B. Jewell <dbj (at) netbsd.org> Sat Jul 4 15:41:32 1998
82 */
83
84 /*
85 * XXX This MCA attachment for NCR 53C90 does not work yet.
86 * After attach, the NCR_INTR gets set according to previously
87 * done Bus Reset, but interrupts are generated later on, so this
88 * stalls on boot waiting for the device detection stuff to finish.
89 * It seem like the device needs some special EOI handling, to tell
90 * it that it can send another interrupt. I need real NCR53C90 docs,
91 * which I don't have currently.
92 * jdolecek 20011201
93 */
94 #error this driver does not work
95
96 #include <sys/types.h>
97 #include <sys/param.h>
98 #include <sys/systm.h>
99 #include <sys/kernel.h>
100 #include <sys/errno.h>
101 #include <sys/ioctl.h>
102 #include <sys/device.h>
103 #include <sys/buf.h>
104 #include <sys/proc.h>
105 #include <sys/user.h>
106 #include <sys/queue.h>
107
108 #include <dev/scsipi/scsi_all.h>
109 #include <dev/scsipi/scsipi_all.h>
110 #include <dev/scsipi/scsiconf.h>
111 #include <dev/scsipi/scsi_message.h>
112
113 #include <machine/bus.h>
114 #include <machine/cpu.h>
115
116 #include <dev/ic/ncr53c9xreg.h>
117 #include <dev/ic/ncr53c9xvar.h>
118
119 #include <dev/mca/espvar.h>
120
121 #include <dev/mca/mcavar.h>
122 #include <dev/mca/mcareg.h>
123 #include <dev/mca/mcadevs.h>
124
125 #if defined(DEBUG) && !defined(NCR53C9X_DEBUG)
126 #define NCR53C9X_DEBUG
127 #endif
128
129 #ifdef NCR53C9X_DEBUG
130 static int esp_mca_debug = 1;
131 #define DPRINTF(x) if (esp_mca_debug) printf x;
132 #else
133 #define DPRINTF(x)
134 #endif
135
136 #define ESP_MCA_IOSIZE 0x20
137
138 static void esp_mca_attach __P((struct device *, struct device *, void *));
139 static int esp_mca_match __P((struct device *, struct cfdata *, void *));
140
141 /* Linkup to the rest of the kernel */
142 struct cfattach esp_mca_ca = {
143 sizeof(struct esp_softc), esp_mca_match, esp_mca_attach
144 };
145
146 /*
147 * Functions and the switch for the MI code.
148 */
149 static u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
150 static void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
151 static int esp_dma_isintr __P((struct ncr53c9x_softc *));
152 static void esp_dma_reset __P((struct ncr53c9x_softc *));
153 static int esp_dma_intr __P((struct ncr53c9x_softc *));
154 static int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
155 size_t *, int, size_t *));
156 static void esp_dma_go __P((struct ncr53c9x_softc *));
157 static void esp_dma_stop __P((struct ncr53c9x_softc *));
158 static int esp_dma_isactive __P((struct ncr53c9x_softc *));
159
160 static struct ncr53c9x_glue esp_glue = {
161 esp_read_reg,
162 esp_write_reg,
163 esp_dma_isintr,
164 esp_dma_reset,
165 esp_dma_intr,
166 esp_dma_setup,
167 esp_dma_go,
168 esp_dma_stop,
169 esp_dma_isactive,
170 NULL, /* gl_clear_latched_intr */
171 };
172
173 static int
174 esp_mca_match(parent, cf, aux)
175 struct device *parent;
176 struct cfdata *cf;
177 void *aux;
178 {
179 struct mca_attach_args *ma = aux;
180
181 switch (ma->ma_id) {
182 case MCA_PRODUCT_NCR53C90:
183 return 1;
184 }
185
186 return 0;
187 }
188
189 static void
190 esp_mca_attach(parent, self, aux)
191 struct device *parent, *self;
192 void *aux;
193 {
194 struct mca_attach_args *ma = aux;
195 struct esp_softc *esc = (void *)self;
196 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
197 int iobase, scsi_id, irq, drq, error;
198 bus_space_handle_t ioh;
199 int pos2, pos3, pos5;
200
201 static const int ncrmca_iobase[] = {
202 0, 0x240, 0x340, 0x400, 0x420, 0x3240, 0x8240, 0xa240
203 };
204
205 /*
206 * NCR SCSI Adapter (ADF 7f4f)
207 *
208 * POS register 2: (adf pos0)
209 *
210 * 7 6 5 4 3 2 1 0
211 * \_/ \___/ \__ enable: 0=adapter disabled, 1=adapter enabled
212 * | \____ I/O base (32B): 001=0x240 010=0x340 011=0x400
213 * | 100=0x420 101=0x3240 110=0x8240 111=0xa240
214 * \__________ IRQ: 00=3 01=5 10=7 11=9
215 *
216 * POS register 3: (adf pos1)
217 *
218 * 7 6 5 4 3 2 1 0
219 * 1 1 1 | \_____/
220 * | \__ DMA level
221 * \_________ Fairness: 1=enabled 0=disabled
222 *
223 * POS register 5: (adf pos3)
224 *
225 * 7 6 5 4 3 2 1 0
226 * 1 | \___/
227 * | \__ Static Ram: 0xC8000-0xC87FF + XX*0x4000
228 * \___________ Host Adapter ID: 1=7 0=6
229 */
230
231 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
232 pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
233 pos5 = mca_conf_read(ma->ma_mc, ma->ma_slot, 5);
234
235 iobase = ncrmca_iobase[(pos2 & 0x0e) >> 1];
236 irq = 3 + 2*((pos2 & 0x30) >> 4);
237 drq = (pos3 & 0x0f);
238 scsi_id = 6 + ((pos5 & 0x20) ? 1 : 0);
239
240 printf(" slot %d irq %d drq %d: NCR SCSI Adapter (53C90)\n",
241 ma->ma_slot + 1, irq, drq);
242
243 if (bus_space_map(ma->ma_iot, iobase, ESP_MCA_IOSIZE, 0, &ioh)) {
244 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
245 return;
246 }
247
248 esc->sc_iot = ma->ma_iot;
249 esc->sc_ioh = ioh;
250
251 /* Setup DMA map */
252 esc->sc_dmat = ma->ma_dmat;
253 if ((error = mca_dmamap_create(esc->sc_dmat, MAXPHYS,
254 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &esc->sc_xfer, drq)) != 0){
255 printf("%s: couldn't create DMA map - error %d\n",
256 sc->sc_dev.dv_xname, error);
257 return;
258 }
259
260 sc->sc_id = scsi_id;
261 sc->sc_freq = 20; /* Mhz */
262
263 /*
264 * Set up glue for MI code early; we use some of it here.
265 */
266 sc->sc_glue = &esp_glue;
267
268 /*
269 * It is necessary to try to load the 2nd config register here,
270 * to find out what rev the esp chip is, else the ncr53c9x_reset
271 * will not set up the defaults correctly.
272 */
273 sc->sc_cfg1 = sc->sc_id;
274 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE | NCRCFG2_DPE;
275 /* No point setting sc_cfg[345], they won't be used */
276
277 sc->sc_rev = NCR_VARIANT_ESP100;
278 sc->sc_minsync = 0;
279
280 /* max 64KB DMA */
281 sc->sc_maxxfer = 64 * 1024;
282
283 /* Establish interrupt */
284 esc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, ncr53c9x_intr,
285 esc);
286 if (esc->sc_ih == NULL) {
287 printf("%s: couldn't establish interrupt\n",
288 sc->sc_dev.dv_xname);
289 return;
290 }
291
292 /*
293 * Now try to attach all the sub-devices
294 */
295 sc->sc_adapter.adapt_minphys = minphys;
296 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
297
298 /* Do the common parts of attachment. */
299 printf("%s", sc->sc_dev.dv_xname);
300 ncr53c9x_attach(sc);
301
302 /* Wait until the SCSI Bus Reset completes */
303 while((NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) == 0)
304 DELAY(10);
305 ncr53c9x_intr(sc);
306 }
307
308 /*
309 * Glue functions.
310 */
311
312 static u_char
313 esp_read_reg(sc, reg)
314 struct ncr53c9x_softc *sc;
315 int reg;
316 {
317 struct esp_softc *esc = (struct esp_softc *)sc;
318
319 return (bus_space_read_1(esc->sc_iot, esc->sc_ioh, reg));
320 }
321
322 static void
323 esp_write_reg(sc, reg, val)
324 struct ncr53c9x_softc *sc;
325 int reg;
326 u_char val;
327 {
328 struct esp_softc *esc = (struct esp_softc *)sc;
329
330 bus_space_write_1(esc->sc_iot, esc->sc_ioh, reg, val);
331 }
332
333 static int
334 esp_dma_isintr(sc)
335 struct ncr53c9x_softc *sc;
336 {
337 DPRINTF(("[esp_dma_isintr] "));
338 return (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT);
339 }
340
341 static void
342 esp_dma_reset(sc)
343 struct ncr53c9x_softc *sc;
344 {
345 struct esp_softc *esc = (struct esp_softc *)sc;
346
347 DPRINTF(("[esp_dma_reset] "));
348
349 if (esc->sc_flags & ESP_XFER_LOADED) {
350 bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
351 esc->sc_flags &= ~ESP_XFER_LOADED;
352 }
353 }
354
355 static int
356 esp_dma_intr(sc)
357 struct ncr53c9x_softc *sc;
358 {
359 struct esp_softc *esc = (struct esp_softc *) sc;
360 DPRINTF(("[esp_dma_intr] "));
361
362 if ((esc->sc_flags & ESP_XFER_ACTIVE) == 0) {
363 printf("%s: dma_intr--inactive DMA\n", sc->sc_dev.dv_xname);
364 return (-1);
365 }
366
367 if ((sc->sc_espintr & NCRINTR_BS) == 0)
368 goto ok;
369
370 /* do something */
371
372 ok:
373 esc->sc_flags &= ~ESP_XFER_ACTIVE;
374 return (0);
375 }
376
377 /*
378 * Setup DMA transfer.
379 */
380 static int
381 esp_dma_setup(sc, addr, len, datain, dmasize)
382 struct ncr53c9x_softc *sc;
383 caddr_t *addr;
384 size_t *len;
385 int datain;
386 size_t *dmasize;
387 {
388 struct esp_softc *esc = (struct esp_softc *) sc;
389 int error;
390 int fl;
391
392 DPRINTF(("[esp_dma_setup] "));
393
394 /* Load the buffer for DMA transfer. */
395 fl = (datain) ? BUS_DMA_READ : BUS_DMA_WRITE;
396
397 if ((error = bus_dmamap_load(esc->sc_dmat, esc->sc_xfer, *addr,
398 *len, NULL, BUS_DMA_STREAMING|fl))) {
399 printf("%s: esp_dma_setup: unable to load DMA buffer - error %d\n",
400 sc->sc_dev.dv_xname, error);
401 return (error);
402 }
403
404 bus_dmamap_sync(esc->sc_dmat, esc->sc_xfer, 0,
405 *len, (datain) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
406
407 esc->sc_flags |= ESP_XFER_LOADED;
408
409 return (0);
410 }
411
412 static void
413 esp_dma_go(sc)
414 struct ncr53c9x_softc *sc;
415 {
416 struct esp_softc *esc = (struct esp_softc *) sc;
417 DPRINTF(("[esp_dma_go] "));
418
419 esc->sc_flags |= ESP_XFER_ACTIVE;
420 }
421
422 static void
423 esp_dma_stop(sc)
424 struct ncr53c9x_softc *sc;
425 {
426 DPRINTF(("[esp_dma_stop] "));
427
428 panic("%s: stop not yet implemented", sc->sc_dev.dv_xname);
429 }
430
431 static int
432 esp_dma_isactive(sc)
433 struct ncr53c9x_softc *sc;
434 {
435 struct esp_softc *esc = (struct esp_softc *) sc;
436 DPRINTF(("[esp_dma_isactive] "));
437
438 return ((esc->sc_flags & ESP_XFER_ACTIVE) != 0);
439 }
440