xref: /netbsd-src/sys/arch/sun3/dev/esp.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: esp.c,v 1.5 1997/08/27 11:24:33 bouyer Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jeremy Cooper and Gordon W. Ross
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * "Front end" glue for the ncr53c9x chip, formerly known as the
41  * Emulex SCSI Processor (ESP) which is what we actually have.
42  */
43 
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/errno.h>
49 #include <sys/ioctl.h>
50 #include <sys/device.h>
51 #include <sys/buf.h>
52 #include <sys/proc.h>
53 #include <sys/user.h>
54 #include <sys/queue.h>
55 #include <sys/malloc.h>
56 
57 #include <dev/scsipi/scsi_all.h>
58 #include <dev/scsipi/scsipi_all.h>
59 #include <dev/scsipi/scsiconf.h>
60 #include <dev/scsipi/scsi_message.h>
61 
62 #include <machine/autoconf.h>
63 
64 #include <dev/ic/ncr53c9xreg.h>
65 #include <dev/ic/ncr53c9xvar.h>
66 
67 #include <sun3x/dev/dmareg.h>
68 #include <sun3x/dev/dmavar.h>
69 
70 #define	ESP_REG_SIZE	(12*4)
71 #define	ESP_DMA_OFF 	0x1000
72 
73 struct esp_softc {
74 	struct ncr53c9x_softc sc_ncr53c9x;	/* glue to MI code */
75 	volatile u_char *sc_reg;		/* the registers */
76 	struct dma_softc *sc_dma;		/* pointer to my dma */
77 };
78 
79 static int	espmatch	__P((struct device *, struct cfdata *, void *));
80 static void	espattach	__P((struct device *, struct device *, void *));
81 
82 struct cfattach esp_ca = {
83 	sizeof(struct esp_softc), espmatch, espattach
84 };
85 
86 struct cfdriver esp_cd = {
87 	NULL, "esp", DV_DULL
88 };
89 
90 struct scsipi_adapter esp_switch = {
91 	ncr53c9x_scsi_cmd,
92 	minphys,		/* no max at this level; handled by DMA code */
93 	NULL,
94 	NULL,
95 };
96 
97 struct scsipi_device esp_dev = {
98 	NULL,			/* Use default error handler */
99 	NULL,			/* have a queue, served by this */
100 	NULL,			/* have no async handler */
101 	NULL,			/* Use default 'done' routine */
102 };
103 
104 /*
105  * Functions and the switch for the MI code.
106  */
107 u_char	esp_read_reg __P((struct ncr53c9x_softc *, int));
108 void	esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
109 int	esp_dma_isintr __P((struct ncr53c9x_softc *));
110 void	esp_dma_reset __P((struct ncr53c9x_softc *));
111 int	esp_dma_intr __P((struct ncr53c9x_softc *));
112 int	esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
113 	    size_t *, int, size_t *));
114 void	esp_dma_go __P((struct ncr53c9x_softc *));
115 void	esp_dma_stop __P((struct ncr53c9x_softc *));
116 int	esp_dma_isactive __P((struct ncr53c9x_softc *));
117 
118 static struct ncr53c9x_glue esp_glue = {
119 	esp_read_reg,
120 	esp_write_reg,
121 	esp_dma_isintr,
122 	esp_dma_reset,
123 	esp_dma_intr,
124 	esp_dma_setup,
125 	esp_dma_go,
126 	esp_dma_stop,
127 	esp_dma_isactive,
128 	NULL,			/* gl_clear_latched_intr */
129 };
130 
131 extern int ncr53c9x_dmaselect;	/* Used in dev/ic/ncr53c9x.c */
132 
133 static int
134 espmatch(parent, cf, aux)
135 	struct device *parent;
136 	struct cfdata *cf;
137 	void *aux;
138 {
139 	struct confargs *ca = aux;
140 
141 	/*
142 	 * Check for the DMA registers.
143 	 */
144 	if (bus_peek(ca->ca_bustype,
145 	    ca->ca_paddr + ESP_DMA_OFF, 4) == -1)
146 		return (0);
147 
148 	/*
149 	 * Check for the esp registers.
150 	 */
151 	if (bus_peek(ca->ca_bustype,
152 	    ca->ca_paddr + (NCR_STAT * 4), 1) == -1)
153 		return (0);
154 
155 	/* If default ipl, fill it in. */
156 	if (ca->ca_intpri == -1)
157 		ca->ca_intpri = 2;
158 
159 	return (1);
160 }
161 
162 /*
163  * Attach this instance, and then all the sub-devices
164  *
165  * In the SPARC port, the dma code used by the esp driver looks like
166  * a separate driver, matched and attached by either the esp driver
167  * or the bus attach function.  However it's not completely separate
168  * in that the sparc esp driver has to go look in dma_cd.cd_devs to
169  * get the softc for the dma driver, and shares its softc, etc.
170  *
171  * The dma module could exist as a separate autoconfig entity, but
172  * that really does not buy us anything, so why bother with that?
173  * In the current sun3x port, the dma chip is treated as just an
174  * extension of the esp driver because that is easier, and the esp
175  * driver is the only one that uses the dma module.
176  */
177 static void
178 espattach(parent, self, aux)
179 	struct device *parent, *self;
180 	void *aux;
181 {
182 	register struct confargs *ca = aux;
183 	struct esp_softc *esc = (void *)self;
184 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
185 
186 	/*
187 	 * Set up glue for MI code early; we use some of it here.
188 	 */
189 	sc->sc_glue = &esp_glue;
190 
191 	/*
192 	 * Map in the ESP registers.
193 	 */
194 	esc->sc_reg = (volatile u_char *)
195 		    bus_mapin(ca->ca_bustype, ca->ca_paddr, NBPG);
196 
197 	/* Other settings */
198 	sc->sc_id = 7;
199 	sc->sc_freq = 20;	/* The 3/80 esp runs at 20 Mhz */
200 
201 	/*
202 	 * Hook up the DMA driver.
203 	 * XXX - Would rather do this later, after the common
204 	 * attach function is done printing its line so the DMA
205 	 * module can print its revision, but the common attach
206 	 * code needs this done first...
207 	 * XXX - Move printf back to MD code?
208 	 */
209 	esc->sc_dma = malloc(sizeof(struct dma_softc), M_DEVBUF, M_NOWAIT);
210 	if (esc->sc_dma == 0)
211 		panic("espattach: malloc dma_softc");
212 	bzero(esc->sc_dma, sizeof(struct dma_softc));
213 	esc->sc_dma->sc_esp = sc; /* Point back to us */
214 	esc->sc_dma->sc_regs = (struct dma_regs *)
215 		(esc->sc_reg + ESP_DMA_OFF);
216 
217 	/*
218 	 * Simulate an attach call here for compatibility with
219 	 * the sparc dma.c module.  It does not print anything.
220 	 */
221 	dmaattach(self, (struct device *) esc->sc_dma, NULL);
222 
223 	/*
224 	 * XXX More of this should be in ncr53c9x_attach(), but
225 	 * XXX should we really poke around the chip that much in
226 	 * XXX the MI code?  Think about this more...
227 	 */
228 
229 	/*
230 	 * It is necessary to try to load the 2nd config register here,
231 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
232 	 * will not set up the defaults correctly.
233 	 */
234 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
235 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
236 	sc->sc_cfg3 = NCRCFG3_CDB;
237 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
238 
239 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
240 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
241 		sc->sc_rev = NCR_VARIANT_ESP100;
242 	} else {
243 		sc->sc_cfg2 = NCRCFG2_SCSI2;
244 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
245 		sc->sc_cfg3 = 0;
246 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
247 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
248 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
249 		if (NCR_READ_REG(sc, NCR_CFG3) !=
250 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
251 			sc->sc_rev = NCR_VARIANT_ESP100A;
252 		} else {
253 			/* NCRCFG2_FE enables > 64K transfers */
254 			sc->sc_cfg2 |= NCRCFG2_FE;
255 			sc->sc_cfg3 = 0;
256 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
257 			sc->sc_rev = NCR_VARIANT_ESP200;
258 		}
259 	}
260 
261 	/*
262 	 * XXX minsync and maxxfer _should_ be set up in MI code,
263 	 * XXX but it appears to have some dependency on what sort
264 	 * XXX of DMA we're hooked up to, etc.
265 	 */
266 
267 	/*
268 	 * This is the value used to start sync negotiations
269 	 * Note that the NCR register "SYNCTP" is programmed
270 	 * in "clocks per byte", and has a minimum value of 4.
271 	 * The SCSI period used in negotiation is one-fourth
272 	 * of the time (in nanoseconds) needed to transfer one byte.
273 	 * Since the chip's clock is given in MHz, we have the following
274 	 * formula: 4 * period = (1000 / freq) * 4
275 	 */
276 	sc->sc_minsync = 1000 / sc->sc_freq;
277 
278 	/*
279 	 * Alas, we must now modify the value a bit, because it's
280 	 * only valid when can switch on FASTCLK and FASTSCSI bits
281 	 * in config register 3...
282 	 */
283 	switch (sc->sc_rev) {
284 	case NCR_VARIANT_ESP100:
285 		sc->sc_maxxfer = 64 * 1024;
286 		sc->sc_minsync = 0;	/* No synch on old chip? */
287 		/* Avoid hardware bug by using DMA when selecting targets */
288 		/* ncr53c9x_dmaselect = 1; */
289 		break;
290 
291 	case NCR_VARIANT_ESP100A:
292 		sc->sc_maxxfer = 64 * 1024;
293 		/* Min clocks/byte is 5 */
294 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
295 		break;
296 
297 	case NCR_VARIANT_ESP200:
298 		sc->sc_maxxfer = 16 * 1024 * 1024;
299 		/* XXX - do actually set FAST* bits */
300 		break;
301 	}
302 
303 	/* and the interuppts */
304 	isr_add_autovect((void*)ncr53c9x_intr, sc, ca->ca_intpri);
305 	evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
306 
307 	/* Do the common parts of attachment. */
308 	ncr53c9x_attach(sc, &esp_switch, &esp_dev);
309 }
310 
311 
312 /*
313  * Glue functions.
314  */
315 
316 u_char
317 esp_read_reg(sc, reg)
318 	struct ncr53c9x_softc *sc;
319 	int reg;
320 {
321 	struct esp_softc *esc = (struct esp_softc *)sc;
322 
323 	return (esc->sc_reg[reg * 4]);
324 }
325 
326 void
327 esp_write_reg(sc, reg, val)
328 	struct ncr53c9x_softc *sc;
329 	int reg;
330 	u_char val;
331 {
332 	struct esp_softc *esc = (struct esp_softc *)sc;
333 	u_char v = val;
334 
335 	esc->sc_reg[reg * 4] = v;
336 }
337 
338 int
339 esp_dma_isintr(sc)
340 	struct ncr53c9x_softc *sc;
341 {
342 	struct esp_softc *esc = (struct esp_softc *)sc;
343 
344 	return (dma_isintr(esc->sc_dma));
345 }
346 
347 void
348 esp_dma_reset(sc)
349 	struct ncr53c9x_softc *sc;
350 {
351 	struct esp_softc *esc = (struct esp_softc *)sc;
352 
353 	dma_reset(esc->sc_dma);
354 }
355 
356 int
357 esp_dma_intr(sc)
358 	struct ncr53c9x_softc *sc;
359 {
360 	struct esp_softc *esc = (struct esp_softc *)sc;
361 
362 	return (espdmaintr(esc->sc_dma));
363 }
364 
365 int
366 esp_dma_setup(sc, addr, len, datain, dmasize)
367 	struct ncr53c9x_softc *sc;
368 	caddr_t *addr;
369 	size_t *len;
370 	int datain;
371 	size_t *dmasize;
372 {
373 	struct esp_softc *esc = (struct esp_softc *)sc;
374 
375 	return (dma_setup(esc->sc_dma, addr, len, datain, dmasize));
376 }
377 
378 void
379 esp_dma_go(sc)
380 	struct ncr53c9x_softc *sc;
381 {
382 	struct esp_softc *esc = (struct esp_softc *)sc;
383 
384 	/* Start DMA */
385 	DMACSR(esc->sc_dma) |= D_EN_DMA;
386 	esc->sc_dma->sc_active = 1;
387 }
388 
389 void
390 esp_dma_stop(sc)
391 	struct ncr53c9x_softc *sc;
392 {
393 	struct esp_softc *esc = (struct esp_softc *)sc;
394 
395 	DMACSR(esc->sc_dma) &= ~D_EN_DMA;
396 }
397 
398 int
399 esp_dma_isactive(sc)
400 	struct ncr53c9x_softc *sc;
401 {
402 	struct esp_softc *esc = (struct esp_softc *)sc;
403 
404 	return (esc->sc_dma->sc_active);
405 }
406