xref: /netbsd/sys/arch/sparc/dev/esp_obio.c (revision 6550d01e)
1 /*	$NetBSD: esp_obio.c,v 1.23 2008/04/28 20:23:35 martin 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  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: esp_obio.c,v 1.23 2008/04/28 20:23:35 martin Exp $");
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/errno.h>
41 #include <sys/device.h>
42 #include <sys/buf.h>
43 
44 #include <dev/scsipi/scsi_all.h>
45 #include <dev/scsipi/scsipi_all.h>
46 #include <dev/scsipi/scsiconf.h>
47 #include <dev/scsipi/scsi_message.h>
48 
49 #include <machine/bus.h>
50 #include <machine/autoconf.h>
51 #include <machine/intr.h>
52 
53 #include <dev/ic/lsi64854reg.h>
54 #include <dev/ic/lsi64854var.h>
55 
56 #include <dev/ic/ncr53c9xreg.h>
57 #include <dev/ic/ncr53c9xvar.h>
58 
59 #include <dev/sbus/sbusvar.h>
60 
61 struct esp_softc {
62 	struct ncr53c9x_softc sc_ncr53c9x;	/* glue to MI code */
63 	bus_space_tag_t		sc_bustag;
64 	bus_dma_tag_t		sc_dmatag;
65 	bus_space_handle_t	sc_reg;		/* the registers */
66 	struct lsi64854_softc	*sc_dma;	/* pointer to my dma */
67 };
68 
69 
70 int	espmatch_obio(device_t, cfdata_t, void *);
71 void	espattach_obio(device_t, device_t, void *);
72 
73 /* Linkup to the rest of the kernel */
74 CFATTACH_DECL_NEW(esp_obio, sizeof(struct esp_softc),
75     espmatch_obio, espattach_obio, NULL, NULL);
76 
77 /*
78  * Functions and the switch for the MI code.
79  */
80 static uint8_t	esp_read_reg(struct ncr53c9x_softc *, int);
81 static void	esp_write_reg(struct ncr53c9x_softc *, int, uint8_t);
82 static int	esp_dma_isintr(struct ncr53c9x_softc *);
83 static void	esp_dma_reset(struct ncr53c9x_softc *);
84 static int	esp_dma_intr(struct ncr53c9x_softc *);
85 static int	esp_dma_setup(struct ncr53c9x_softc *, uint8_t **,
86 				    size_t *, int, size_t *);
87 static void	esp_dma_go(struct ncr53c9x_softc *);
88 static void	esp_dma_stop(struct ncr53c9x_softc *);
89 static int	esp_dma_isactive(struct ncr53c9x_softc *);
90 
91 static struct ncr53c9x_glue esp_obio_glue = {
92 	esp_read_reg,
93 	esp_write_reg,
94 	esp_dma_isintr,
95 	esp_dma_reset,
96 	esp_dma_intr,
97 	esp_dma_setup,
98 	esp_dma_go,
99 	esp_dma_stop,
100 	esp_dma_isactive,
101 	NULL,			/* gl_clear_latched_intr */
102 };
103 
104 int
105 espmatch_obio(device_t parent, cfdata_t cf, void *aux)
106 {
107 	union obio_attach_args *uoba = aux;
108 	struct obio4_attach_args *oba;
109 
110 	if (uoba->uoba_isobio4 == 0)
111 		return 0;
112 
113 	oba = &uoba->uoba_oba4;
114 	return bus_space_probe(oba->oba_bustag, oba->oba_paddr,
115 				1,	/* probe size */
116 				0,	/* offset */
117 				0,	/* flags */
118 				NULL, NULL);
119 }
120 
121 void
122 espattach_obio(device_t parent, device_t self, void *aux)
123 {
124 	struct esp_softc *esc = device_private(self);
125 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
126 	union obio_attach_args *uoba = aux;
127 	struct obio4_attach_args *oba = &uoba->uoba_oba4;
128 	device_t dma_dev;
129 
130 	sc->sc_dev = self;
131 
132 	esc->sc_bustag = oba->oba_bustag;
133 	esc->sc_dmatag = oba->oba_dmatag;
134 
135 	sc->sc_id = 7;
136 	sc->sc_freq = 24000000;
137 
138 	/*
139 	 * Find the DMA by poking around the dma device structures and
140 	 * set the reverse pointer.
141 	 */
142 	dma_dev = device_find_by_driver_unit("dma", device_unit(self));
143 	if (dma_dev == NULL)
144 		panic("%s: no corresponding DMA device", device_xname(self));
145 	esc->sc_dma = device_private(dma_dev);
146 	esc->sc_dma->sc_client = sc;
147 
148 	if (bus_space_map(oba->oba_bustag, oba->oba_paddr,
149 			  16,	/* size (of ncr53c9xreg) */
150 			  BUS_SPACE_MAP_LINEAR,
151 			  &esc->sc_reg) != 0) {
152 		aprint_error(": cannot map registers\n");
153 		return;
154 	}
155 
156 	/*
157 	 * Set up glue for MI code early; we use some of it here.
158 	 */
159 	sc->sc_glue = &esp_obio_glue;
160 
161 	/* gimme MHz */
162 	sc->sc_freq /= 1000000;
163 
164 	/*
165 	 * XXX More of this should be in ncr53c9x_attach(), but
166 	 * XXX should we really poke around the chip that much in
167 	 * XXX the MI code?  Think about this more...
168 	 */
169 
170 	/*
171 	 * It is necessary to try to load the 2nd config register here,
172 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
173 	 * will not set up the defaults correctly.
174 	 */
175 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
176 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
177 	sc->sc_cfg3 = NCRCFG3_CDB;
178 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
179 
180 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
181 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
182 		sc->sc_rev = NCR_VARIANT_ESP100;
183 	} else {
184 		sc->sc_cfg2 = NCRCFG2_SCSI2;
185 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
186 		sc->sc_cfg3 = 0;
187 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
188 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
189 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
190 		if (NCR_READ_REG(sc, NCR_CFG3) !=
191 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
192 			sc->sc_rev = NCR_VARIANT_ESP100A;
193 		} else {
194 			/* NCRCFG2_FE enables > 64K transfers */
195 			sc->sc_cfg2 |= NCRCFG2_FE;
196 			sc->sc_cfg3 = 0;
197 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
198 			sc->sc_rev = NCR_VARIANT_ESP200;
199 		}
200 	}
201 
202 	/*
203 	 * XXX minsync and maxxfer _should_ be set up in MI code,
204 	 * XXX but it appears to have some dependency on what sort
205 	 * XXX of DMA we're hooked up to, etc.
206 	 */
207 
208 	/*
209 	 * This is the value used to start sync negotiations
210 	 * Note that the NCR register "SYNCTP" is programmed
211 	 * in "clocks per byte", and has a minimum value of 4.
212 	 * The SCSI period used in negotiation is one-fourth
213 	 * of the time (in nanoseconds) needed to transfer one byte.
214 	 * Since the chip's clock is given in MHz, we have the following
215 	 * formula: 4 * period = (1000 / freq) * 4
216 	 */
217 	sc->sc_minsync = 1000 / sc->sc_freq;
218 
219 	/*
220 	 * Alas, we must now modify the value a bit, because it's
221 	 * only valid when can switch on FASTCLK and FASTSCSI bits
222 	 * in config register 3...
223 	 */
224 	switch (sc->sc_rev) {
225 	case NCR_VARIANT_ESP100:
226 		sc->sc_maxxfer = 64 * 1024;
227 		sc->sc_minsync = 0;	/* No synch on old chip? */
228 		break;
229 
230 	case NCR_VARIANT_ESP100A:
231 		sc->sc_maxxfer = 64 * 1024;
232 		/* Min clocks/byte is 5 */
233 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
234 		break;
235 
236 	case NCR_VARIANT_ESP200:
237 		sc->sc_maxxfer = 16 * 1024 * 1024;
238 		/* XXX - do actually set FAST* bits */
239 		break;
240 	}
241 
242 	/* Establish interrupt channel */
243 	bus_intr_establish(esc->sc_bustag, oba->oba_pri, IPL_BIO,
244 	    ncr53c9x_intr, sc);
245 
246 	/* register interrupt stats */
247 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
248 	    device_xname(self), "intr");
249 
250 	/* Do the common parts of attachment. */
251 	sc->sc_adapter.adapt_minphys = minphys;
252 	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
253 	ncr53c9x_attach(sc);
254 	sc->sc_features |= NCR_F_DMASELECT;
255 }
256 
257 /*
258  * Glue functions.
259  */
260 
261 static uint8_t
262 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
263 {
264 	struct esp_softc *esc = (struct esp_softc *)sc;
265 
266 	return bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
267 }
268 
269 static void
270 esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v)
271 {
272 	struct esp_softc *esc = (struct esp_softc *)sc;
273 
274 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
275 }
276 
277 static int
278 esp_dma_isintr(struct ncr53c9x_softc *sc)
279 {
280 	struct esp_softc *esc = (struct esp_softc *)sc;
281 
282 	return DMA_ISINTR(esc->sc_dma);
283 }
284 
285 static void
286 esp_dma_reset(struct ncr53c9x_softc *sc)
287 {
288 	struct esp_softc *esc = (struct esp_softc *)sc;
289 
290 	DMA_RESET(esc->sc_dma);
291 }
292 
293 static int
294 esp_dma_intr(struct ncr53c9x_softc *sc)
295 {
296 	struct esp_softc *esc = (struct esp_softc *)sc;
297 
298 	return DMA_INTR(esc->sc_dma);
299 }
300 
301 static int
302 esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
303     int datain, size_t *dmasize)
304 {
305 	struct esp_softc *esc = (struct esp_softc *)sc;
306 
307 	return DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize);
308 }
309 
310 static void
311 esp_dma_go(struct ncr53c9x_softc *sc)
312 {
313 	struct esp_softc *esc = (struct esp_softc *)sc;
314 
315 	DMA_GO(esc->sc_dma);
316 }
317 
318 static void
319 esp_dma_stop(struct ncr53c9x_softc *sc)
320 {
321 	struct esp_softc *esc = (struct esp_softc *)sc;
322 	uint32_t csr;
323 
324 	csr = L64854_GCSR(esc->sc_dma);
325 	csr &= ~D_EN_DMA;
326 	L64854_SCSR(esc->sc_dma, csr);
327 }
328 
329 static int
330 esp_dma_isactive(struct ncr53c9x_softc *sc)
331 {
332 	struct esp_softc *esc = (struct esp_softc *)sc;
333 
334 	return DMA_ISACTIVE(esc->sc_dma);
335 }
336