1 /* $NetBSD: qec.c,v 1.49 2009/09/19 04:48:18 tsutsui Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: qec.c,v 1.49 2009/09/19 04:48:18 tsutsui Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/errno.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
44 #include <machine/autoconf.h>
46 #include <dev/sbus/sbusvar.h>
47 #include <dev/sbus/qecreg.h>
48 #include <dev/sbus/qecvar.h>
50 static int qecprint(void *, const char *);
51 static int qecmatch(device_t
, cfdata_t
, void *);
52 static void qecattach(device_t
, device_t
, void *);
53 void qec_init(struct qec_softc
*);
55 static int qec_bus_map(
57 bus_addr_t
, /*coded slot+offset*/
60 vaddr_t
, /*preferred virtual address */
61 bus_space_handle_t
*);
62 static void *qec_intr_establish(
64 int, /*bus interrupt priority*/
65 int, /*`device class' interrupt level*/
66 int (*)(void *), /*handler*/
68 void (*)(void)); /*optional fast trap handler*/
70 CFATTACH_DECL_NEW(qec
, sizeof(struct qec_softc
),
71 qecmatch
, qecattach
, NULL
, NULL
);
74 qecprint(void *aux
, const char *busname
)
76 struct sbus_attach_args
*sa
= aux
;
77 bus_space_tag_t t
= sa
->sa_bustag
;
78 struct qec_softc
*sc
= t
->cookie
;
80 sa
->sa_bustag
= sc
->sc_bustag
; /* XXX */
81 sbus_print(aux
, busname
); /* XXX */
82 sa
->sa_bustag
= t
; /* XXX */
87 qecmatch(device_t parent
, cfdata_t cf
, void *aux
)
89 struct sbus_attach_args
*sa
= aux
;
91 return (strcmp(cf
->cf_name
, sa
->sa_name
) == 0);
95 * Attach all the sub-devices we can find
98 qecattach(device_t parent
, device_t self
, void *aux
)
100 struct sbus_attach_args
*sa
= aux
;
101 struct qec_softc
*sc
= device_private(self
);
102 struct sbus_softc
*sbsc
= device_private(parent
);
106 bus_space_handle_t bh
;
110 sc
->sc_bustag
= sa
->sa_bustag
;
111 sc
->sc_dmatag
= sa
->sa_dmatag
;
114 if (sa
->sa_nreg
< 2) {
115 printf("%s: only %d register sets\n",
116 device_xname(self
), sa
->sa_nreg
);
120 if (sbus_bus_map(sa
->sa_bustag
,
121 sa
->sa_reg
[0].oa_space
,
122 sa
->sa_reg
[0].oa_base
,
123 sa
->sa_reg
[0].oa_size
,
124 0, &sc
->sc_regs
) != 0) {
125 aprint_error_dev(self
, "attach: cannot map registers\n");
130 * This device's "register space 1" is just a buffer where the
131 * Lance ring-buffers can be stored. Note the buffer's location
132 * and size, so the child driver can pick them up.
134 if (sbus_bus_map(sa
->sa_bustag
,
135 sa
->sa_reg
[1].oa_space
,
136 sa
->sa_reg
[1].oa_base
,
137 sa
->sa_reg
[1].oa_size
,
138 BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
139 aprint_error_dev(self
, "attach: cannot map registers\n");
142 sc
->sc_buffer
= (void *)bus_space_vaddr(sa
->sa_bustag
, bh
);
143 sc
->sc_bufsiz
= (bus_size_t
)sa
->sa_reg
[1].oa_size
;
145 /* Get number of on-board channels */
146 sc
->sc_nchannels
= prom_getpropint(node
, "#channels", -1);
147 if (sc
->sc_nchannels
== -1) {
148 printf(": no channels\n");
153 * Get transfer burst size from PROM
155 sbusburst
= sbsc
->sc_burst
;
157 sbusburst
= SBUS_BURST_32
- 1; /* 1->16 */
159 sc
->sc_burst
= prom_getpropint(node
, "burst-sizes", -1);
160 if (sc
->sc_burst
== -1)
161 /* take SBus burst sizes */
162 sc
->sc_burst
= sbusburst
;
164 /* Clamp at parent's burst sizes */
165 sc
->sc_burst
&= sbusburst
;
167 /* Allocate a bus tag */
168 sbt
= bus_space_tag_alloc(sc
->sc_bustag
, sc
);
170 aprint_error_dev(self
, "attach: out of memory\n");
174 sbt
->sparc_bus_map
= qec_bus_map
;
175 sbt
->sparc_intr_establish
= qec_intr_establish
;
178 * Collect address translations from the OBP.
180 error
= prom_getprop(node
, "ranges", sizeof(struct openprom_range
),
181 &sbt
->nranges
, &sbt
->ranges
);
187 panic("%s: error getting ranges property", device_xname(self
));
191 * Save interrupt information for use in our qec_intr_establish()
192 * function below. Apparently, the intr level for the quad
193 * ethernet board (qe) is stored in the QEC node rather than
194 * separately in each of the QE nodes.
196 * XXX - qe.c should call bus_intr_establish() with `level = 0'..
197 * XXX - maybe we should have our own attach args for all that.
199 sc
->sc_intr
= sa
->sa_intr
;
201 printf(": %dK memory\n", sc
->sc_bufsiz
/ 1024);
205 /* search through children */
206 for (node
= firstchild(node
); node
; node
= nextsibling(node
)) {
207 struct sbus_attach_args sax
;
208 sbus_setup_attach_args(sbsc
,
209 sbt
, sc
->sc_dmatag
, node
, &sax
);
210 (void)config_found(self
, (void *)&sax
, qecprint
);
211 sbus_destroy_attach_args(&sax
);
216 qec_bus_map(bus_space_tag_t t
, bus_addr_t ba
, bus_size_t size
, int flags
,
217 vaddr_t va
, bus_space_handle_t
*hp
)
222 if ((error
= bus_space_translate_address_generic(
223 t
->ranges
, t
->nranges
, &ba
)) != 0)
226 return (bus_space_map(t
->parent
, ba
, size
, flags
, hp
));
230 qec_intr_establish(bus_space_tag_t t
, int pri
, int level
,
231 int (*handler
)(void *), void *arg
, void (*fastvec
)(void))
232 /* (*fastvec)(void): ignored */
234 struct qec_softc
*sc
= t
->cookie
;
238 * qe.c calls bus_intr_establish() with `pri == 0'
239 * XXX - see also comment in qec_attach().
241 if (sc
->sc_intr
== NULL
) {
242 printf("%s: warning: no interrupts\n",
243 device_xname(sc
->sc_dev
));
246 pri
= sc
->sc_intr
->oi_pri
;
249 return (bus_intr_establish(t
->parent
, pri
, level
, handler
, arg
));
253 qec_init(struct qec_softc
*sc
)
255 bus_space_tag_t t
= sc
->sc_bustag
;
256 bus_space_handle_t qr
= sc
->sc_regs
;
257 uint32_t v
, burst
= 0, psize
;
260 /* First, reset the controller */
261 bus_space_write_4(t
, qr
, QEC_QRI_CTRL
, QEC_CTRL_RESET
);
262 for (i
= 0; i
< 1000; i
++) {
264 v
= bus_space_read_4(t
, qr
, QEC_QRI_CTRL
);
265 if ((v
& QEC_CTRL_RESET
) == 0)
270 * Cut available buffer size into receive and transmit buffers.
271 * XXX - should probably be done in be & qe driver...
273 v
= sc
->sc_msize
= sc
->sc_bufsiz
/ sc
->sc_nchannels
;
274 bus_space_write_4(t
, qr
, QEC_QRI_MSIZE
, v
);
276 v
= sc
->sc_rsize
= sc
->sc_bufsiz
/ (sc
->sc_nchannels
* 2);
277 bus_space_write_4(t
, qr
, QEC_QRI_RSIZE
, v
);
278 bus_space_write_4(t
, qr
, QEC_QRI_TSIZE
, v
);
280 psize
= sc
->sc_nchannels
== 1 ? QEC_PSIZE_2048
: 0;
281 bus_space_write_4(t
, qr
, QEC_QRI_PSIZE
, psize
);
283 if (sc
->sc_burst
& SBUS_BURST_64
)
284 burst
= QEC_CTRL_B64
;
285 else if (sc
->sc_burst
& SBUS_BURST_32
)
286 burst
= QEC_CTRL_B32
;
288 burst
= QEC_CTRL_B16
;
290 v
= bus_space_read_4(t
, qr
, QEC_QRI_CTRL
);
291 v
= (v
& QEC_CTRL_MODEMASK
) | burst
;
292 bus_space_write_4(t
, qr
, QEC_QRI_CTRL
, v
);
296 * Common routine to initialize the QEC packet ring buffer.
297 * Called from be & qe drivers.
300 qec_meminit(struct qec_ring
*qr
, unsigned int pktbufsz
)
302 bus_addr_t txbufdma
, rxbufdma
;
305 unsigned int ntbuf
, nrbuf
, i
;
308 dma
= qr
->rb_dmabase
;
310 ntbuf
= qr
->rb_ntbuf
;
311 nrbuf
= qr
->rb_nrbuf
;
314 * Allocate transmit descriptors
316 qr
->rb_txd
= (struct qec_xd
*)p
;
318 p
+= QEC_XD_RING_MAXSIZE
* sizeof(struct qec_xd
);
319 dma
+= QEC_XD_RING_MAXSIZE
* sizeof(struct qec_xd
);
322 * Allocate receive descriptors
324 qr
->rb_rxd
= (struct qec_xd
*)p
;
326 p
+= QEC_XD_RING_MAXSIZE
* sizeof(struct qec_xd
);
327 dma
+= QEC_XD_RING_MAXSIZE
* sizeof(struct qec_xd
);
331 * Allocate transmit buffers
335 p
+= ntbuf
* pktbufsz
;
336 dma
+= ntbuf
* pktbufsz
;
339 * Allocate receive buffers
343 p
+= nrbuf
* pktbufsz
;
344 dma
+= nrbuf
* pktbufsz
;
347 * Initialize transmit buffer descriptors
349 for (i
= 0; i
< QEC_XD_RING_MAXSIZE
; i
++) {
350 qr
->rb_txd
[i
].xd_addr
=
351 (uint32_t)(txbufdma
+ (i
% ntbuf
) * pktbufsz
);
352 qr
->rb_txd
[i
].xd_flags
= 0;
356 * Initialize receive buffer descriptors
358 for (i
= 0; i
< QEC_XD_RING_MAXSIZE
; i
++) {
359 qr
->rb_rxd
[i
].xd_addr
=
360 (uint32_t)(rxbufdma
+ (i
% nrbuf
) * pktbufsz
);
361 qr
->rb_rxd
[i
].xd_flags
= (i
< nrbuf
)
362 ? QEC_XD_OWN
| (pktbufsz
& QEC_XD_LENGTH
)
366 qr
->rb_tdhead
= qr
->rb_tdtail
= 0;