1 /*	$OpenBSD: esp.c,v 1.21 2003/06/05 12:27:02 deraadt Exp $	*/
2 /*	$NetBSD: esp.c,v 1.69 1997/08/27 11:24:18 bouyer Exp $	*/
3 
4 /*
5  * Copyright (c) 1997 Jason R. Thorpe.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed for the NetBSD Project
19  *	by Jason R. Thorpe.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by Charles M. Hannum.
49  * 4. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 /*
65  * Copyright (c) 1994 Peter Galbavy
66  * Copyright (c) 1995 Paul Kranenburg
67  * All rights reserved.
68  *
69  * Redistribution and use in source and binary forms, with or without
70  * modification, are permitted provided that the following conditions
71  * are met:
72  * 1. Redistributions of source code must retain the above copyright
73  *    notice, this list of conditions and the following disclaimer.
74  * 2. Redistributions in binary form must reproduce the above copyright
75  *    notice, this list of conditions and the following disclaimer in the
76  *    documentation and/or other materials provided with the distribution.
77  *
78  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
79  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
80  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
81  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
82  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
83  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
84  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
86  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
87  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
88  * POSSIBILITY OF SUCH DAMAGE.
89  */
90 
91 /*
92  * Based on aic6360 by Jarle Greipsland
93  *
94  * Acknowledgements: Many of the algorithms used in this driver are
95  * inspired by the work of Julian Elischer (julian@tfs.com) and
96  * Charles Hannum (mycroft@duality.gnu.ai.mit.edu).  Thanks a million!
97  */
98 
99 #include <sys/types.h>
100 #include <sys/param.h>
101 #include <sys/systm.h>
102 #include <sys/kernel.h>
103 #include <sys/errno.h>
104 #include <sys/ioctl.h>
105 #include <sys/device.h>
106 #include <sys/buf.h>
107 #include <sys/proc.h>
108 #include <sys/user.h>
109 #include <sys/queue.h>
110 
111 #include <scsi/scsi_all.h>
112 #include <scsi/scsiconf.h>
113 #include <scsi/scsi_message.h>
114 
115 #include <machine/cpu.h>
116 #include <machine/autoconf.h>
117 
118 #include <dev/ic/ncr53c9xreg.h>
119 #include <dev/ic/ncr53c9xvar.h>
120 
121 #include <sparc/dev/sbusvar.h>
122 #include <sparc/dev/dmareg.h>
123 #include <sparc/dev/dmavar.h>
124 #include <sparc/dev/espvar.h>
125 
126 void	espattach(struct device *, struct device *, void *);
127 int	espmatch(struct device *, void *, void *);
128 
129 /* Linkup to the rest of the kernel */
130 struct cfattach esp_ca = {
131 	sizeof(struct esp_softc), espmatch, espattach
132 };
133 
134 struct scsi_adapter esp_switch = {
135 	ncr53c9x_scsi_cmd,
136 	minphys,		/* no max at this level; handled by DMA code */
137 	NULL,
138 	NULL,
139 };
140 
141 struct scsi_device esp_dev = {
142 	NULL,			/* Use default error handler */
143 	NULL,			/* have a queue, served by this */
144 	NULL,			/* have no async handler */
145 	NULL,			/* Use default 'done' routine */
146 };
147 
148 /*
149  * Functions and the switch for the MI code.
150  */
151 u_char	esp_read_reg(struct ncr53c9x_softc *, int);
152 void	esp_write_reg(struct ncr53c9x_softc *, int, u_char);
153 int	esp_dma_isintr(struct ncr53c9x_softc *);
154 void	esp_dma_reset(struct ncr53c9x_softc *);
155 int	esp_dma_intr(struct ncr53c9x_softc *);
156 int	esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
157 	    size_t *, int, size_t *);
158 void	esp_dma_go(struct ncr53c9x_softc *);
159 void	esp_dma_stop(struct ncr53c9x_softc *);
160 int	esp_dma_isactive(struct ncr53c9x_softc *);
161 
162 struct ncr53c9x_glue esp_glue = {
163 	esp_read_reg,
164 	esp_write_reg,
165 	esp_dma_isintr,
166 	esp_dma_reset,
167 	esp_dma_intr,
168 	esp_dma_setup,
169 	esp_dma_go,
170 	esp_dma_stop,
171 	esp_dma_isactive,
172 	NULL,			/* gl_clear_latched_intr */
173 };
174 
175 int
espmatch(parent,vcf,aux)176 espmatch(parent, vcf, aux)
177 	struct device *parent;
178 	void *vcf, *aux;
179 {
180 	register struct cfdata *cf = vcf;
181 	register struct confargs *ca = aux;
182 	register struct romaux *ra = &ca->ca_ra;
183 
184 	if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
185 		return (0);
186 #if defined(SUN4C) || defined(SUN4M)
187 	if (ca->ca_bustype == BUS_SBUS) {
188 		if (!sbus_testdma((struct sbus_softc *)parent, ca))
189 			return (0);
190 		return (1);
191 	}
192 #endif
193 	ra->ra_len = NBPG;
194 	return (probeget(ra->ra_vaddr, 1) != -1);
195 }
196 
197 /*
198  * Attach this instance, and then all the sub-devices
199  */
200 void
espattach(parent,self,aux)201 espattach(parent, self, aux)
202 	struct device *parent, *self;
203 	void *aux;
204 {
205 	register struct confargs *ca = aux;
206 	struct esp_softc *esc = (void *)self;
207 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
208 	struct bootpath *bp;
209 	int dmachild = strncmp(parent->dv_xname, "dma", 3) == 0;
210 
211 	/*
212 	 * Set up glue for MI code early; we use some of it here.
213 	 */
214 	sc->sc_glue = &esp_glue;
215 
216 	/*
217 	 * Make sure things are sane. I don't know if this is ever
218 	 * necessary, but it seem to be in all of Torek's code.
219 	 */
220 	if (ca->ca_ra.ra_nintr != 1) {
221 		printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
222 		return;
223 	}
224 
225 	esc->sc_pri = ca->ca_ra.ra_intr[0].int_pri;
226 	printf(" pri %d", esc->sc_pri);
227 
228 	/*
229 	 * Map my registers in, if they aren't already in virtual
230 	 * address space.
231 	 */
232 	if (ca->ca_ra.ra_vaddr)
233 		esc->sc_reg = (volatile u_char *) ca->ca_ra.ra_vaddr;
234 	else {
235 		esc->sc_reg = (volatile u_char *)
236 		    mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
237 	}
238 
239 	/* Other settings */
240 	esc->sc_node = ca->ca_ra.ra_node;
241 	if (ca->ca_bustype == BUS_SBUS) {
242 		sc->sc_id = getpropint(esc->sc_node, "initiator-id", 7);
243 		sc->sc_freq = getpropint(esc->sc_node, "clock-frequency", -1);
244 	} else {
245 		sc->sc_id = 7;
246 		sc->sc_freq = 24000000;
247 	}
248 	if (sc->sc_freq < 0)
249 		sc->sc_freq = ((struct sbus_softc *)
250 		    sc->sc_dev.dv_parent)->sc_clockfreq;
251 
252 	/* gimme MHz */
253 	sc->sc_freq /= 1000000;
254 
255 	if (dmachild) {
256 		esc->sc_dma = (struct dma_softc *)parent;
257 		esc->sc_dma->sc_esp = esc;
258 	} else {
259 		/*
260 		 * find the DMA by poking around the dma device structures
261 		 *
262 		 * What happens here is that if the dma driver has not been
263 		 * configured, then this returns a NULL pointer. Then when the
264 		 * dma actually gets configured, it does the opposing test, and
265 		 * if the sc->sc_esp field in it's softc is NULL, then tries to
266 		 * find the matching esp driver.
267 		 */
268 		esc->sc_dma = (struct dma_softc *)
269 			getdevunit("dma", sc->sc_dev.dv_unit);
270 
271 		/*
272 		 * and a back pointer to us, for DMA
273 		 */
274 		if (esc->sc_dma)
275 			esc->sc_dma->sc_esp = esc;
276 		else {
277 			printf("\n");
278 			panic("espattach: no dma found");
279 		}
280 	}
281 
282 	/*
283 	 * XXX More of this should be in ncr53c9x_attach(), but
284 	 * XXX should we really poke around the chip that much in
285 	 * XXX the MI code?  Think about this more...
286 	 */
287 
288 	/*
289 	 * It is necessary to try to load the 2nd config register here,
290 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
291 	 * will not set up the defaults correctly.
292 	 */
293 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
294 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
295 	sc->sc_cfg3 = NCRCFG3_CDB;
296 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
297 
298 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
299 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
300 		sc->sc_rev = NCR_VARIANT_ESP100;
301 	} else {
302 		sc->sc_cfg2 = NCRCFG2_SCSI2;
303 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
304 		sc->sc_cfg3 = 0;
305 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
306 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
307 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
308 		if (NCR_READ_REG(sc, NCR_CFG3) !=
309 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
310 			sc->sc_rev = NCR_VARIANT_ESP100A;
311 		} else {
312 			/* NCRCFG2_FE enables > 64K transfers */
313 			sc->sc_cfg2 |= NCRCFG2_FE;
314 			sc->sc_cfg3 = 0;
315 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
316 			sc->sc_rev = NCR_VARIANT_ESP200;
317 		}
318 	}
319 
320 	/*
321 	 * XXX minsync and maxxfer _should_ be set up in MI code,
322 	 * XXX but it appears to have some dependency on what sort
323 	 * XXX of DMA we're hooked up to, etc.
324 	 */
325 
326 	/*
327 	 * This is the value used to start sync negotiations
328 	 * Note that the NCR register "SYNCTP" is programmed
329 	 * in "clocks per byte", and has a minimum value of 4.
330 	 * The SCSI period used in negotiation is one-fourth
331 	 * of the time (in nanoseconds) needed to transfer one byte.
332 	 * Since the chip's clock is given in MHz, we have the following
333 	 * formula: 4 * period = (1000 / freq) * 4
334 	 */
335 	sc->sc_minsync = 1000 / sc->sc_freq;
336 
337 	/*
338 	 * Alas, we must now modify the value a bit, because it's
339 	 * only valid when can switch on FASTCLK and FASTSCSI bits
340 	 * in config register 3...
341 	 */
342 	switch (sc->sc_rev) {
343 	case NCR_VARIANT_ESP100:
344 		sc->sc_maxxfer = 64 * 1024;
345 		sc->sc_minsync = 0;	/* No synch on old chip? */
346 		break;
347 
348 	case NCR_VARIANT_ESP100A:
349 		sc->sc_maxxfer = 64 * 1024;
350 		/* Min clocks/byte is 5 */
351 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
352 		break;
353 
354 	case NCR_VARIANT_ESP200:
355 		sc->sc_maxxfer = 16 * 1024 * 1024;
356 		/* XXX - do actually set FAST* bits */
357 		break;
358 	}
359 
360 	/* add me to the sbus structures */
361 	esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
362 #if defined(SUN4C) || defined(SUN4M)
363 	if (ca->ca_bustype == BUS_SBUS) {
364 		if (dmachild)
365 			sbus_establish(&esc->sc_sd, sc->sc_dev.dv_parent);
366 		else
367 			sbus_establish(&esc->sc_sd, &sc->sc_dev);
368 	}
369 #endif /* SUN4C || SUN4M */
370 
371 	/* and the interuppts */
372 	esc->sc_ih.ih_fun = (void *) ncr53c9x_intr;
373 	esc->sc_ih.ih_arg = sc;
374 	intr_establish(esc->sc_pri, &esc->sc_ih, IPL_BIO);
375 	evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
376 
377 	/*
378 	 * If the boot path is "esp" at the moment and it's me, then
379 	 * walk our pointer to the sub-device, ready for the config
380 	 * below.
381 	 */
382 	bp = ca->ca_ra.ra_bp;
383 	switch (ca->ca_bustype) {
384 	case BUS_SBUS:
385 		if (bp != NULL && strcmp(bp->name, "esp") == 0 &&
386 		    SAME_ESP(sc, bp, ca))
387 			bootpath_store(1, bp + 1);
388 		break;
389 	default:
390 		if (bp != NULL && strcmp(bp->name, "esp") == 0 &&
391 			bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)
392 			bootpath_store(1, bp + 1);
393 		break;
394 	}
395 
396 	/* Do the common parts of attachment. */
397 	ncr53c9x_attach(sc, &esp_switch, &esp_dev);
398 
399 	/* Turn on target selection using the `dma' method */
400 	sc->sc_features |= NCR_F_DMASELECT;
401 
402 	bootpath_store(1, NULL);
403 }
404 
405 /*
406  * Glue functions.
407  */
408 
409 u_char
esp_read_reg(sc,reg)410 esp_read_reg(sc, reg)
411 	struct ncr53c9x_softc *sc;
412 	int reg;
413 {
414 	struct esp_softc *esc = (struct esp_softc *)sc;
415 
416 	return (esc->sc_reg[reg * 4]);
417 }
418 
419 void
esp_write_reg(sc,reg,val)420 esp_write_reg(sc, reg, val)
421 	struct ncr53c9x_softc *sc;
422 	int reg;
423 	u_char val;
424 {
425 	struct esp_softc *esc = (struct esp_softc *)sc;
426 	u_char v = val;
427 
428 	esc->sc_reg[reg * 4] = v;
429 }
430 
431 int
esp_dma_isintr(sc)432 esp_dma_isintr(sc)
433 	struct ncr53c9x_softc *sc;
434 {
435 	struct esp_softc *esc = (struct esp_softc *)sc;
436 
437 	return (DMA_ISINTR(esc->sc_dma));
438 }
439 
440 void
esp_dma_reset(sc)441 esp_dma_reset(sc)
442 	struct ncr53c9x_softc *sc;
443 {
444 	struct esp_softc *esc = (struct esp_softc *)sc;
445 
446 	DMA_RESET(esc->sc_dma);
447 }
448 
449 int
esp_dma_intr(sc)450 esp_dma_intr(sc)
451 	struct ncr53c9x_softc *sc;
452 {
453 	struct esp_softc *esc = (struct esp_softc *)sc;
454 
455 	return (DMA_INTR(esc->sc_dma));
456 }
457 
458 int
esp_dma_setup(sc,addr,len,datain,dmasize)459 esp_dma_setup(sc, addr, len, datain, dmasize)
460 	struct ncr53c9x_softc *sc;
461 	caddr_t *addr;
462 	size_t *len;
463 	int datain;
464 	size_t *dmasize;
465 {
466 	struct esp_softc *esc = (struct esp_softc *)sc;
467 
468 	return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
469 }
470 
471 void
esp_dma_go(sc)472 esp_dma_go(sc)
473 	struct ncr53c9x_softc *sc;
474 {
475 	struct esp_softc *esc = (struct esp_softc *)sc;
476 
477 	DMA_GO(esc->sc_dma);
478 }
479 
480 void
esp_dma_stop(sc)481 esp_dma_stop(sc)
482 	struct ncr53c9x_softc *sc;
483 {
484 	struct esp_softc *esc = (struct esp_softc *)sc;
485 
486 	DMACSR(esc->sc_dma) &= ~D_EN_DMA;
487 }
488 
489 int
esp_dma_isactive(sc)490 esp_dma_isactive(sc)
491 	struct ncr53c9x_softc *sc;
492 {
493 	struct esp_softc *esc = (struct esp_softc *)sc;
494 
495 	return (DMA_ISACTIVE(esc->sc_dma));
496 }
497