esp_sbus.c revision 1.4 1 /* $NetBSD: esp_sbus.c,v 1.4 1998/10/10 00:28:29 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 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; Paul Kranenburg.
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 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/errno.h>
45 #include <sys/device.h>
46 #include <sys/buf.h>
47
48 #include <dev/scsipi/scsi_all.h>
49 #include <dev/scsipi/scsipi_all.h>
50 #include <dev/scsipi/scsiconf.h>
51 #include <dev/scsipi/scsi_message.h>
52
53 #include <machine/bus.h>
54 #include <machine/autoconf.h>
55 #include <machine/cpu.h>
56
57 #include <dev/ic/lsi64854reg.h>
58 #include <dev/ic/lsi64854var.h>
59
60 #include <dev/ic/ncr53c9xreg.h>
61 #include <dev/ic/ncr53c9xvar.h>
62
63 #include <dev/sbus/sbusvar.h>
64
65 struct esp_softc {
66 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
67 struct sbusdev sc_sd; /* sbus device */
68
69 bus_space_tag_t sc_bustag;
70 bus_dma_tag_t sc_dmatag;
71
72 bus_space_handle_t sc_reg; /* the registers */
73 struct lsi64854_softc *sc_dma; /* pointer to my dma */
74
75 int sc_pri; /* SBUS priority */
76 };
77
78 /*
79 * Is this esp on the bootpath?
80 * We may get two forms of the bootpath:
81 * (1) ../sbus (at) .../esp@<offset>,<slot>/sd@.. (PROM v3 style)
82 * (2) /sbus0/esp0/sd@.. (PROM v2 style)
83 */
84 #define SAME_ESP(sc, bp, sa) \
85 ((bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset) || \
86 (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit))
87
88 void espattach_sbus __P((struct device *, struct device *, void *));
89 void espattach_dma __P((struct device *, struct device *, void *));
90 int espmatch_sbus __P((struct device *, struct cfdata *, void *));
91
92 static void espattach __P((struct esp_softc *));
93
94 /* Linkup to the rest of the kernel */
95 struct cfattach esp_sbus_ca = {
96 sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
97 };
98 struct cfattach esp_dma_ca = {
99 sizeof(struct esp_softc), espmatch_sbus, espattach_dma
100 };
101
102 static struct scsipi_adapter esp_sbus_switch = {
103 ncr53c9x_scsi_cmd,
104 minphys, /* no max at this level; handled by DMA code */
105 NULL, /* scsipi_ioctl */
106 };
107
108 static struct scsipi_device esp_sbus_dev = {
109 NULL, /* Use default error handler */
110 NULL, /* have a queue, served by this */
111 NULL, /* have no async handler */
112 NULL, /* Use default 'done' routine */
113 };
114
115 /*
116 * Functions and the switch for the MI code.
117 */
118 static u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
119 static void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
120 static int esp_dma_isintr __P((struct ncr53c9x_softc *));
121 static void esp_dma_reset __P((struct ncr53c9x_softc *));
122 static int esp_dma_intr __P((struct ncr53c9x_softc *));
123 static int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
124 size_t *, int, size_t *));
125 static void esp_dma_go __P((struct ncr53c9x_softc *));
126 static void esp_dma_stop __P((struct ncr53c9x_softc *));
127 static int esp_dma_isactive __P((struct ncr53c9x_softc *));
128
129 static struct ncr53c9x_glue esp_sbus_glue = {
130 esp_read_reg,
131 esp_write_reg,
132 esp_dma_isintr,
133 esp_dma_reset,
134 esp_dma_intr,
135 esp_dma_setup,
136 esp_dma_go,
137 esp_dma_stop,
138 esp_dma_isactive,
139 NULL, /* gl_clear_latched_intr */
140 };
141
142 int
143 espmatch_sbus(parent, cf, aux)
144 struct device *parent;
145 struct cfdata *cf;
146 void *aux;
147 {
148 struct sbus_attach_args *sa = aux;
149
150 return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
151 }
152
153 void
154 espattach_sbus(parent, self, aux)
155 struct device *parent, *self;
156 void *aux;
157 {
158 struct esp_softc *esc = (void *)self;
159 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
160 struct sbus_attach_args *sa = aux;
161
162 esc->sc_bustag = sa->sa_bustag;
163 esc->sc_dmatag = sa->sa_dmatag;
164
165 sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
166 sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
167 if (sc->sc_freq < 0)
168 sc->sc_freq = ((struct sbus_softc *)
169 sc->sc_dev.dv_parent)->sc_clockfreq;
170
171 /*
172 * Find the DMA by poking around the dma device structures
173 *
174 * What happens here is that if the dma driver has not been
175 * configured, then this returns a NULL pointer. Then when the
176 * dma actually gets configured, it does the opposing test, and
177 * if the sc->sc_esp field in it's softc is NULL, then tries to
178 * find the matching esp driver.
179 */
180 esc->sc_dma = (struct lsi64854_softc *)
181 getdevunit("dma", sc->sc_dev.dv_unit);
182
183 /*
184 * and a back pointer to us, for DMA
185 */
186 if (esc->sc_dma)
187 esc->sc_dma->sc_client = sc;
188 else {
189 printf("\n");
190 panic("espattach: no dma found");
191 }
192
193 /*
194 * Map my registers in, if they aren't already in virtual
195 * address space.
196 */
197 if (sa->sa_npromvaddrs)
198 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
199 else {
200 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
201 sa->sa_offset,
202 sa->sa_size,
203 BUS_SPACE_MAP_LINEAR,
204 0, &esc->sc_reg) != 0) {
205 printf("%s @ sbus: cannot map registers\n",
206 self->dv_xname);
207 return;
208 }
209 }
210
211 esc->sc_pri = sa->sa_pri;
212
213 /* add me to the sbus structures */
214 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
215 sbus_establish(&esc->sc_sd, &sc->sc_dev);
216
217 if (sa->sa_bp != NULL && strcmp(sa->sa_bp->name, "esp") == 0 &&
218 SAME_ESP(sc, sa->sa_bp, sa))
219 bootpath_store(1, sa->sa_bp + 1);
220
221 espattach(esc);
222 }
223
224 void
225 espattach_dma(parent, self, aux)
226 struct device *parent, *self;
227 void *aux;
228 {
229 struct esp_softc *esc = (void *)self;
230 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
231 struct sbus_attach_args *sa = aux;
232
233 esc->sc_bustag = sa->sa_bustag;
234 esc->sc_dmatag = sa->sa_dmatag;
235
236 sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
237 sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
238
239 esc->sc_dma = (struct lsi64854_softc *)parent;
240 esc->sc_dma->sc_client = sc;
241
242 /*
243 * Map my registers in, if they aren't already in virtual
244 * address space.
245 */
246 if (sa->sa_npromvaddrs)
247 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
248 else {
249 if (bus_space_map2(sa->sa_bustag,
250 sa->sa_slot,
251 sa->sa_offset,
252 sa->sa_size,
253 BUS_SPACE_MAP_LINEAR,
254 0, &esc->sc_reg) != 0) {
255 printf("%s @ dma: cannot map registers\n",
256 self->dv_xname);
257 return;
258 }
259 }
260
261 /* Establish interrupt handler */
262 esc->sc_pri = sa->sa_pri;
263
264 /* Assume SBus is grandparent */
265 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
266 sbus_establish(&esc->sc_sd, parent);
267
268 if (sa->sa_bp != NULL && strcmp(sa->sa_bp->name, "esp") == 0 &&
269 SAME_ESP(sc, sa->sa_bp, sa))
270 bootpath_store(1, sa->sa_bp + 1);
271
272 espattach(esc);
273 }
274
275
276 /*
277 * Attach this instance, and then all the sub-devices
278 */
279 void
280 espattach(esc)
281 struct esp_softc *esc;
282 {
283 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
284 void *icookie;
285
286 /*
287 * Set up glue for MI code early; we use some of it here.
288 */
289 sc->sc_glue = &esp_sbus_glue;
290
291 /* gimme Mhz */
292 sc->sc_freq /= 1000000;
293
294 /*
295 * XXX More of this should be in ncr53c9x_attach(), but
296 * XXX should we really poke around the chip that much in
297 * XXX the MI code? Think about this more...
298 */
299
300 /*
301 * It is necessary to try to load the 2nd config register here,
302 * to find out what rev the esp chip is, else the ncr53c9x_reset
303 * will not set up the defaults correctly.
304 */
305 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
306 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
307 sc->sc_cfg3 = NCRCFG3_CDB;
308 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
309
310 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
311 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
312 sc->sc_rev = NCR_VARIANT_ESP100;
313 } else {
314 sc->sc_cfg2 = NCRCFG2_SCSI2;
315 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
316 sc->sc_cfg3 = 0;
317 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
318 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
319 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
320 if (NCR_READ_REG(sc, NCR_CFG3) !=
321 (NCRCFG3_CDB | NCRCFG3_FCLK)) {
322 sc->sc_rev = NCR_VARIANT_ESP100A;
323 } else {
324 /* NCRCFG2_FE enables > 64K transfers */
325 sc->sc_cfg2 |= NCRCFG2_FE;
326 sc->sc_cfg3 = 0;
327 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
328 sc->sc_rev = NCR_VARIANT_ESP200;
329 }
330 }
331
332 /*
333 * XXX minsync and maxxfer _should_ be set up in MI code,
334 * XXX but it appears to have some dependency on what sort
335 * XXX of DMA we're hooked up to, etc.
336 */
337
338 /*
339 * This is the value used to start sync negotiations
340 * Note that the NCR register "SYNCTP" is programmed
341 * in "clocks per byte", and has a minimum value of 4.
342 * The SCSI period used in negotiation is one-fourth
343 * of the time (in nanoseconds) needed to transfer one byte.
344 * Since the chip's clock is given in MHz, we have the following
345 * formula: 4 * period = (1000 / freq) * 4
346 */
347 sc->sc_minsync = 1000 / sc->sc_freq;
348
349 /*
350 * Alas, we must now modify the value a bit, because it's
351 * only valid when can switch on FASTCLK and FASTSCSI bits
352 * in config register 3...
353 */
354 switch (sc->sc_rev) {
355 case NCR_VARIANT_ESP100:
356 sc->sc_maxxfer = 64 * 1024;
357 sc->sc_minsync = 0; /* No synch on old chip? */
358 break;
359
360 case NCR_VARIANT_ESP100A:
361 sc->sc_maxxfer = 64 * 1024;
362 /* Min clocks/byte is 5 */
363 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
364 break;
365
366 case NCR_VARIANT_ESP200:
367 sc->sc_maxxfer = 16 * 1024 * 1024;
368 /* XXX - do actually set FAST* bits */
369 break;
370 }
371
372 /* Establish interrupt channel */
373 icookie = bus_intr_establish(esc->sc_bustag,
374 esc->sc_pri, 0,
375 (int(*)__P((void*)))ncr53c9x_intr, sc);
376
377 /* register interrupt stats */
378 evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
379
380 /* Do the common parts of attachment. */
381 ncr53c9x_attach(sc, &esp_sbus_switch, &esp_sbus_dev);
382
383 /* Turn on target selection using the `dma' method */
384 ncr53c9x_dmaselect = 1;
385
386 bootpath_store(1, NULL);
387 }
388
389 /*
390 * Glue functions.
391 */
392
393 u_char
394 esp_read_reg(sc, reg)
395 struct ncr53c9x_softc *sc;
396 int reg;
397 {
398 struct esp_softc *esc = (struct esp_softc *)sc;
399
400 return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4));
401 }
402
403 void
404 esp_write_reg(sc, reg, v)
405 struct ncr53c9x_softc *sc;
406 int reg;
407 u_char v;
408 {
409 struct esp_softc *esc = (struct esp_softc *)sc;
410
411 bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
412 }
413
414 int
415 esp_dma_isintr(sc)
416 struct ncr53c9x_softc *sc;
417 {
418 struct esp_softc *esc = (struct esp_softc *)sc;
419
420 return (DMA_ISINTR(esc->sc_dma));
421 }
422
423 void
424 esp_dma_reset(sc)
425 struct ncr53c9x_softc *sc;
426 {
427 struct esp_softc *esc = (struct esp_softc *)sc;
428
429 DMA_RESET(esc->sc_dma);
430 }
431
432 int
433 esp_dma_intr(sc)
434 struct ncr53c9x_softc *sc;
435 {
436 struct esp_softc *esc = (struct esp_softc *)sc;
437
438 return (DMA_INTR(esc->sc_dma));
439 }
440
441 int
442 esp_dma_setup(sc, addr, len, datain, dmasize)
443 struct ncr53c9x_softc *sc;
444 caddr_t *addr;
445 size_t *len;
446 int datain;
447 size_t *dmasize;
448 {
449 struct esp_softc *esc = (struct esp_softc *)sc;
450
451 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
452 }
453
454 void
455 esp_dma_go(sc)
456 struct ncr53c9x_softc *sc;
457 {
458 struct esp_softc *esc = (struct esp_softc *)sc;
459
460 DMA_GO(esc->sc_dma);
461 }
462
463 void
464 esp_dma_stop(sc)
465 struct ncr53c9x_softc *sc;
466 {
467 struct esp_softc *esc = (struct esp_softc *)sc;
468 u_int32_t csr;
469
470 csr = L64854_GCSR(esc->sc_dma);
471 csr &= ~D_EN_DMA;
472 L64854_SCSR(esc->sc_dma, csr);
473 }
474
475 int
476 esp_dma_isactive(sc)
477 struct ncr53c9x_softc *sc;
478 {
479 struct esp_softc *esc = (struct esp_softc *)sc;
480
481 return (DMA_ISACTIVE(esc->sc_dma));
482 }
483