xref: /netbsd-src/sys/dev/sbus/esp_sbus.c (revision 5aefcfdc06931dd97e76246d2fe0302f7b3fe094)
1 /*	$NetBSD: esp_sbus.c,v 1.12 2000/12/03 23:31:13 eeh 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/intr.h>
55 #include <machine/autoconf.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 void	espattach_sbus	__P((struct device *, struct device *, void *));
79 void	espattach_dma	__P((struct device *, struct device *, void *));
80 int	espmatch_sbus	__P((struct device *, struct cfdata *, void *));
81 
82 
83 /* Linkup to the rest of the kernel */
84 struct cfattach esp_sbus_ca = {
85 	sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
86 };
87 struct cfattach esp_dma_ca = {
88 	sizeof(struct esp_softc), espmatch_sbus, espattach_dma
89 };
90 
91 /*
92  * Functions and the switch for the MI code.
93  */
94 static u_char	esp_read_reg __P((struct ncr53c9x_softc *, int));
95 static void	esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
96 static u_char	esp_rdreg1 __P((struct ncr53c9x_softc *, int));
97 static void	esp_wrreg1 __P((struct ncr53c9x_softc *, int, u_char));
98 static int	esp_dma_isintr __P((struct ncr53c9x_softc *));
99 static void	esp_dma_reset __P((struct ncr53c9x_softc *));
100 static int	esp_dma_intr __P((struct ncr53c9x_softc *));
101 static int	esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
102 				    size_t *, int, size_t *));
103 static void	esp_dma_go __P((struct ncr53c9x_softc *));
104 static void	esp_dma_stop __P((struct ncr53c9x_softc *));
105 static int	esp_dma_isactive __P((struct ncr53c9x_softc *));
106 
107 static struct ncr53c9x_glue esp_sbus_glue = {
108 	esp_read_reg,
109 	esp_write_reg,
110 	esp_dma_isintr,
111 	esp_dma_reset,
112 	esp_dma_intr,
113 	esp_dma_setup,
114 	esp_dma_go,
115 	esp_dma_stop,
116 	esp_dma_isactive,
117 	NULL,			/* gl_clear_latched_intr */
118 };
119 
120 static struct ncr53c9x_glue esp_sbus_glue1 = {
121 	esp_rdreg1,
122 	esp_wrreg1,
123 	esp_dma_isintr,
124 	esp_dma_reset,
125 	esp_dma_intr,
126 	esp_dma_setup,
127 	esp_dma_go,
128 	esp_dma_stop,
129 	esp_dma_isactive,
130 	NULL,			/* gl_clear_latched_intr */
131 };
132 
133 static void	espattach __P((struct esp_softc *, struct ncr53c9x_glue *));
134 
135 int
136 espmatch_sbus(parent, cf, aux)
137 	struct device *parent;
138 	struct cfdata *cf;
139 	void *aux;
140 {
141 	int rv;
142 	struct sbus_attach_args *sa = aux;
143 
144 	rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
145 	    strcmp("ptscII", sa->sa_name) == 0);
146 	return (rv);
147 }
148 
149 void
150 espattach_sbus(parent, self, aux)
151 	struct device *parent, *self;
152 	void *aux;
153 {
154 	struct esp_softc *esc = (void *)self;
155 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
156 	struct sbus_attach_args *sa = aux;
157 
158 	esc->sc_bustag = sa->sa_bustag;
159 	esc->sc_dmatag = sa->sa_dmatag;
160 
161 	sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
162 	sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
163 	if (sc->sc_freq < 0)
164 		sc->sc_freq = ((struct sbus_softc *)
165 		    sc->sc_dev.dv_parent)->sc_clockfreq;
166 
167 	/*
168 	 * Find the DMA by poking around the dma device structures
169 	 *
170 	 * What happens here is that if the dma driver has not been
171 	 * configured, then this returns a NULL pointer. Then when the
172 	 * dma actually gets configured, it does the opposing test, and
173 	 * if the sc->sc_esp field in it's softc is NULL, then tries to
174 	 * find the matching esp driver.
175 	 */
176 	esc->sc_dma = (struct lsi64854_softc *)
177 				getdevunit("dma", sc->sc_dev.dv_unit);
178 
179 	/*
180 	 * and a back pointer to us, for DMA
181 	 */
182 	if (esc->sc_dma)
183 		esc->sc_dma->sc_client = sc;
184 	else {
185 		printf("\n");
186 		panic("espattach: no dma found");
187 	}
188 
189 	/*
190 	 * Map my registers in, if they aren't already in virtual
191 	 * address space.
192 	 */
193 	if (sa->sa_npromvaddrs)
194 		esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
195 	else {
196 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
197 				 sa->sa_offset,
198 				 sa->sa_size,
199 				 BUS_SPACE_MAP_LINEAR,
200 				 0, &esc->sc_reg) != 0) {
201 			printf("%s @ sbus: cannot map registers\n",
202 				self->dv_xname);
203 			return;
204 		}
205 	}
206 
207 	if (sa->sa_nintr == 0) {
208 		/*
209 		 * No interrupt properties: we quit; this might
210 		 * happen on e.g. a Sparc X terminal.
211 		 */
212 		printf("\n%s: no interrupt property\n", self->dv_xname);
213 		return;
214 	}
215 
216 	esc->sc_pri = sa->sa_pri;
217 
218 	/* add me to the sbus structures */
219 	esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
220 	sbus_establish(&esc->sc_sd, &sc->sc_dev);
221 
222 	if (strcmp("ptscII", sa->sa_name) == 0) {
223 		espattach(esc, &esp_sbus_glue1);
224 	} else {
225 		espattach(esc, &esp_sbus_glue);
226 	}
227 }
228 
229 void
230 espattach_dma(parent, self, aux)
231 	struct device *parent, *self;
232 	void *aux;
233 {
234 	struct esp_softc *esc = (void *)self;
235 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
236 	struct sbus_attach_args *sa = aux;
237 
238 	if (strcmp("ptscII", sa->sa_name) == 0) {
239 		return;
240 	}
241 
242 	esc->sc_bustag = sa->sa_bustag;
243 	esc->sc_dmatag = sa->sa_dmatag;
244 
245 	sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
246 	sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
247 
248 	esc->sc_dma = (struct lsi64854_softc *)parent;
249 	esc->sc_dma->sc_client = sc;
250 
251 	/*
252 	 * Map my registers in, if they aren't already in virtual
253 	 * address space.
254 	 */
255 	if (sa->sa_npromvaddrs)
256 		esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
257 	else {
258 		if (bus_space_map2(sa->sa_bustag,
259 				   sa->sa_slot,
260 				   sa->sa_offset,
261 				   sa->sa_size,
262 				   BUS_SPACE_MAP_LINEAR,
263 				   0, &esc->sc_reg) != 0) {
264 			printf("%s @ dma: cannot map registers\n",
265 				self->dv_xname);
266 			return;
267 		}
268 	}
269 
270 	if (sa->sa_nintr == 0) {
271 		/*
272 		 * No interrupt properties: we quit; this might
273 		 * happen on e.g. a Sparc X terminal.
274 		 */
275 		printf("\n%s: no interrupt property\n", self->dv_xname);
276 		return;
277 	}
278 
279 	esc->sc_pri = sa->sa_pri;
280 
281 	/* Assume SBus is grandparent */
282 	esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
283 	sbus_establish(&esc->sc_sd, parent);
284 
285 	espattach(esc, &esp_sbus_glue);
286 }
287 
288 
289 /*
290  * Attach this instance, and then all the sub-devices
291  */
292 void
293 espattach(esc, gluep)
294 	struct esp_softc *esc;
295 	struct ncr53c9x_glue *gluep;
296 {
297 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
298 	void *icookie;
299 
300 	/*
301 	 * Set up glue for MI code early; we use some of it here.
302 	 */
303 	sc->sc_glue = gluep;
304 
305 	/* gimme Mhz */
306 	sc->sc_freq /= 1000000;
307 
308 	/*
309 	 * XXX More of this should be in ncr53c9x_attach(), but
310 	 * XXX should we really poke around the chip that much in
311 	 * XXX the MI code?  Think about this more...
312 	 */
313 
314 	/*
315 	 * It is necessary to try to load the 2nd config register here,
316 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
317 	 * will not set up the defaults correctly.
318 	 */
319 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
320 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
321 	sc->sc_cfg3 = NCRCFG3_CDB | NCRCFG3_QTE;
322 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
323 
324 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
325 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
326 		sc->sc_rev = NCR_VARIANT_ESP100;
327 	} else {
328 		sc->sc_cfg2 = NCRCFG2_SCSI2;
329 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
330 		sc->sc_cfg3 = 0;
331 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
332 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK | NCRCFG3_QTE);
333 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
334 		if (NCR_READ_REG(sc, NCR_CFG3) !=
335 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
336 			sc->sc_rev = NCR_VARIANT_ESP100A;
337 		} else {
338 			/* NCRCFG2_FE enables > 64K transfers */
339 			sc->sc_cfg2 |= NCRCFG2_FE;
340 			sc->sc_cfg3 = 0 | NCRF9XCFG3_QTE;
341 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
342 			sc->sc_rev = NCR_VARIANT_ESP200;
343 		}
344 	}
345 
346 	/*
347 	 * XXX minsync and maxxfer _should_ be set up in MI code,
348 	 * XXX but it appears to have some dependency on what sort
349 	 * XXX of DMA we're hooked up to, etc.
350 	 */
351 
352 	/*
353 	 * This is the value used to start sync negotiations
354 	 * Note that the NCR register "SYNCTP" is programmed
355 	 * in "clocks per byte", and has a minimum value of 4.
356 	 * The SCSI period used in negotiation is one-fourth
357 	 * of the time (in nanoseconds) needed to transfer one byte.
358 	 * Since the chip's clock is given in MHz, we have the following
359 	 * formula: 4 * period = (1000 / freq) * 4
360 	 */
361 	sc->sc_minsync = 1000 / sc->sc_freq;
362 
363 	/*
364 	 * Alas, we must now modify the value a bit, because it's
365 	 * only valid when can switch on FASTCLK and FASTSCSI bits
366 	 * in config register 3...
367 	 */
368 	switch (sc->sc_rev) {
369 	case NCR_VARIANT_ESP100:
370 		sc->sc_maxxfer = 64 * 1024;
371 		sc->sc_minsync = 0;	/* No synch on old chip? */
372 		break;
373 
374 	case NCR_VARIANT_ESP100A:
375 		sc->sc_maxxfer = 64 * 1024;
376 		/* Min clocks/byte is 5 */
377 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
378 		break;
379 
380 	case NCR_VARIANT_ESP200:
381 		sc->sc_maxxfer = 16 * 1024 * 1024;
382 		/* XXX - do actually set FAST* bits */
383 		break;
384 	}
385 
386 	/* Establish interrupt channel */
387 	icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0,
388 				     ncr53c9x_intr, sc);
389 
390 	/* register interrupt stats */
391 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
392 	    sc->sc_dev.dv_xname, "intr");
393 
394 	/* Do the common parts of attachment. */
395 	ncr53c9x_attach(sc, NULL, NULL);
396 
397 	/* Turn on target selection using the `dma' method */
398 	ncr53c9x_dmaselect = 1;
399 }
400 
401 /*
402  * Glue functions.
403  */
404 
405 u_char
406 esp_read_reg(sc, reg)
407 	struct ncr53c9x_softc *sc;
408 	int reg;
409 {
410 	struct esp_softc *esc = (struct esp_softc *)sc;
411 
412 	return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4));
413 }
414 
415 void
416 esp_write_reg(sc, reg, v)
417 	struct ncr53c9x_softc *sc;
418 	int reg;
419 	u_char v;
420 {
421 	struct esp_softc *esc = (struct esp_softc *)sc;
422 
423 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
424 }
425 
426 u_char
427 esp_rdreg1(sc, reg)
428 	struct ncr53c9x_softc *sc;
429 	int reg;
430 {
431 	struct esp_softc *esc = (struct esp_softc *)sc;
432 
433 	return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg));
434 }
435 
436 void
437 esp_wrreg1(sc, reg, v)
438 	struct ncr53c9x_softc *sc;
439 	int reg;
440 	u_char v;
441 {
442 	struct esp_softc *esc = (struct esp_softc *)sc;
443 
444 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
445 }
446 
447 int
448 esp_dma_isintr(sc)
449 	struct ncr53c9x_softc *sc;
450 {
451 	struct esp_softc *esc = (struct esp_softc *)sc;
452 
453 	return (DMA_ISINTR(esc->sc_dma));
454 }
455 
456 void
457 esp_dma_reset(sc)
458 	struct ncr53c9x_softc *sc;
459 {
460 	struct esp_softc *esc = (struct esp_softc *)sc;
461 
462 	DMA_RESET(esc->sc_dma);
463 }
464 
465 int
466 esp_dma_intr(sc)
467 	struct ncr53c9x_softc *sc;
468 {
469 	struct esp_softc *esc = (struct esp_softc *)sc;
470 
471 	return (DMA_INTR(esc->sc_dma));
472 }
473 
474 int
475 esp_dma_setup(sc, addr, len, datain, dmasize)
476 	struct ncr53c9x_softc *sc;
477 	caddr_t *addr;
478 	size_t *len;
479 	int datain;
480 	size_t *dmasize;
481 {
482 	struct esp_softc *esc = (struct esp_softc *)sc;
483 
484 	return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
485 }
486 
487 void
488 esp_dma_go(sc)
489 	struct ncr53c9x_softc *sc;
490 {
491 	struct esp_softc *esc = (struct esp_softc *)sc;
492 
493 	DMA_GO(esc->sc_dma);
494 }
495 
496 void
497 esp_dma_stop(sc)
498 	struct ncr53c9x_softc *sc;
499 {
500 	struct esp_softc *esc = (struct esp_softc *)sc;
501 	u_int32_t csr;
502 
503 	csr = L64854_GCSR(esc->sc_dma);
504 	csr &= ~D_EN_DMA;
505 	L64854_SCSR(esc->sc_dma, csr);
506 }
507 
508 int
509 esp_dma_isactive(sc)
510 	struct ncr53c9x_softc *sc;
511 {
512 	struct esp_softc *esc = (struct esp_softc *)sc;
513 
514 	return (DMA_ISACTIVE(esc->sc_dma));
515 }
516 
517 #include "opt_ddb.h"
518 #ifdef DDB
519 #include <machine/db_machdep.h>
520 #include <ddb/db_output.h>
521 
522 void db_esp __P((db_expr_t, int, db_expr_t, char*));
523 
524 void
525 db_esp(addr, have_addr, count, modif)
526 	db_expr_t addr;
527 	int have_addr;
528 	db_expr_t count;
529 	char *modif;
530 {
531 	struct ncr53c9x_softc *sc;
532 	struct ncr53c9x_ecb *ecb;
533 	struct ncr53c9x_linfo *li;
534 	int u, t, i;
535 
536 	for (u=0; u<10; u++) {
537 		sc = (struct ncr53c9x_softc *)
538 			getdevunit("esp", u);
539 		if (!sc) continue;
540 
541 		db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n",
542 			  u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
543 			  sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
544 		db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
545 			  sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
546 			  sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
547 			  sc->sc_imess[0]);
548 		db_printf("ready: ");
549 		for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) {
550 			db_printf("ecb %p ", ecb);
551 			if (ecb == ecb->chain.tqe_next) {
552 				db_printf("\nWARNING: tailq loop on ecb %p", ecb);
553 				break;
554 			}
555 		}
556 		db_printf("\n");
557 
558 		for (t=0; t<NCR_NTARG; t++) {
559 			LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
560 				db_printf("t%d lun %d untagged %p busy %d used %x\n",
561 					  t, (int)li->lun, li->untagged, li->busy,
562 					  li->used);
563 				for (i=0; i<256; i++)
564 					if ((ecb = li->queued[i])) {
565 						db_printf("ecb %p tag %x\n", ecb, i);
566 					}
567 			}
568 		}
569 	}
570 }
571 #endif
572