1 /* $NetBSD: if_cs_ofisa.c,v 1.23 2009/09/22 14:55:19 tsutsui Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: if_cs_ofisa.c,v 1.23 2009/09/22 14:55:19 tsutsui Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/socket.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
48 #include <net/if_ether.h>
49 #include <net/if_media.h>
51 #include <netinet/in.h>
52 #include <netinet/if_inarp.h>
58 #include <dev/ofw/openfirm.h>
59 #include <dev/isa/isavar.h>
60 #include <dev/ofisa/ofisavar.h>
62 #include <dev/ic/cs89x0reg.h>
63 #include <dev/ic/cs89x0var.h>
64 #include <dev/isa/cs89x0isavar.h>
66 static int cs_ofisa_match(device_t
, cfdata_t
, void *);
67 static void cs_ofisa_attach(device_t
, device_t
, void *);
69 CFATTACH_DECL_NEW(cs_ofisa
, sizeof(struct cs_softc_isa
),
70 cs_ofisa_match
, cs_ofisa_attach
, NULL
, NULL
);
73 cs_ofisa_match(device_t parent
, cfdata_t cf
, void *aux
)
75 struct ofisa_attach_args
*aa
= aux
;
76 static const char *const compatible_strings
[] = {
78 /* XXX CS8920, CS8920M? */
84 if (of_compatible(aa
->oba
.oba_phandle
, compatible_strings
) != -1)
86 #ifdef _CS_OFISA_MD_MATCH
88 rv
= cs_ofisa_md_match(parent
, cf
, aux
);
94 cs_ofisa_attach(device_t parent
, device_t self
, void *aux
)
96 struct cs_softc_isa
*isc
= device_private(self
);
97 struct cs_softc
*sc
= &isc
->sc_cs
;
98 struct ofisa_attach_args
*aa
= aux
;
99 struct ofisa_reg_desc reg
[2];
100 struct ofisa_intr_desc intr
;
101 struct ofisa_dma_desc dma
;
102 int i
, n
, *media
, nmedia
, defmedia
;
103 bus_addr_t io_addr
, mem_addr
;
105 const char *message
= NULL
;
110 sc
->sc_iot
= aa
->iot
;
111 sc
->sc_memt
= aa
->memt
;
114 * We're living on an OFW. We have to ask the OFW what our
115 * registers and interrupts properties look like.
119 * 1 i/o register region
120 * 0 or 1 memory region
125 io_addr
= mem_addr
= -1;
127 n
= ofisa_reg_get(aa
->oba
.oba_phandle
, reg
, 2);
128 #ifdef _CS_OFISA_MD_REG_FIXUP
129 n
= cs_ofisa_md_reg_fixup(parent
, self
, aux
, reg
, 2, n
);
131 if (n
< 1 || n
> 2) {
132 printf(": error getting register data\n");
136 for (i
= 0; i
< n
; i
++) {
137 if (reg
[i
].type
== OFISA_REG_TYPE_IO
) {
138 if (io_addr
!= (bus_addr_t
) -1) {
139 printf(": multiple I/O regions\n");
142 if (reg
[i
].len
!= CS8900_IOSIZE
) {
143 printf(": weird register size (%lu, expected %d)\n",
144 (unsigned long)reg
[i
].len
, CS8900_IOSIZE
);
147 io_addr
= reg
[i
].addr
;
149 if (mem_addr
!= (bus_addr_t
) -1) {
150 printf(": multiple memory regions\n");
153 if (reg
[i
].len
!= CS8900_MEMSIZE
) {
154 printf(": weird register size (%lu, expected %d)\n",
155 (unsigned long)reg
[i
].len
, CS8900_MEMSIZE
);
158 mem_addr
= reg
[i
].addr
;
162 n
= ofisa_intr_get(aa
->oba
.oba_phandle
, &intr
, 1);
163 #ifdef _CS_OFISA_MD_INTR_FIXUP
164 n
= cs_ofisa_md_intr_fixup(parent
, self
, aux
, &intr
, 1, n
);
167 printf(": error getting interrupt data\n");
170 sc
->sc_irq
= intr
.irq
;
172 if (CS8900_IRQ_ISVALID(sc
->sc_irq
) == 0) {
173 printf(": invalid IRQ %d\n", sc
->sc_irq
);
178 n
= ofisa_dma_get(aa
->oba
.oba_phandle
, &dma
, 1);
179 #ifdef _CS_OFISA_MD_DMA_FIXUP
180 n
= cs_ofisa_md_dma_fixup(parent
, self
, aux
, &dma
, 1, n
);
183 isc
->sc_drq
= dma
.drq
;
185 if (io_addr
== (bus_addr_t
) -1) {
186 printf(": no I/O space\n");
189 if (bus_space_map(sc
->sc_iot
, io_addr
, CS8900_IOSIZE
, 0,
191 printf(": unable to map register space\n");
195 if (mem_addr
!= (bus_addr_t
) -1) {
196 if (bus_space_map(sc
->sc_memt
, mem_addr
, CS8900_MEMSIZE
, 0,
198 message
= "unable to map memory space";
200 sc
->sc_cfgflags
|= CFGFLG_MEM_MODE
;
201 sc
->sc_pktpgaddr
= mem_addr
;
205 /* Dig MAC address out of the firmware. */
206 if (OF_getprop(aa
->oba
.oba_phandle
, "mac-address", enaddr
,
207 sizeof(enaddr
)) < 0) {
208 printf(": unable to get Ethernet address\n");
212 /* Dig media out of the firmware. */
213 media
= of_network_decode_media(aa
->oba
.oba_phandle
, &nmedia
,
215 #ifdef _CS_OFISA_MD_MEDIA_FIXUP
216 media
= cs_ofisa_md_media_fixup(parent
, self
, aux
, media
, &nmedia
,
220 printf(": unable to get media information\n");
224 n
= OF_getproplen(aa
->oba
.oba_phandle
, "model");
227 if (OF_getprop(aa
->oba
.oba_phandle
, "model", model
, n
) != n
)
228 model
= NULL
; /* Safe; alloca is on-stack */
231 printf(": %s\n", model
);
236 printf("%s: %s\n", device_xname(self
), message
);
238 if (defmedia
== -1) {
239 aprint_error_dev(self
, "unable to get default media\n");
240 defmedia
= media
[0]; /* XXX What to do? */
243 sc
->sc_ih
= isa_intr_establish(isc
->sc_ic
, sc
->sc_irq
, intr
.share
,
244 IPL_NET
, cs_intr
, sc
);
245 if (sc
->sc_ih
== NULL
) {
246 aprint_error_dev(self
, "unable to establish interrupt\n");
250 #ifdef _CS_OFISA_MD_CFGFLAGS_FIXUP
251 sc
->sc_cfgflags
|= cs_ofisa_md_cfgflags_fixup(parent
, self
, aux
);
254 sc
->sc_dma_chipinit
= cs_isa_dma_chipinit
;
255 sc
->sc_dma_attach
= cs_isa_dma_attach
;
256 sc
->sc_dma_process_rx
= cs_process_rx_dma
;
258 cs_attach(sc
, enaddr
, media
, nmedia
, defmedia
);
260 /* This is malloc'd. */
261 free(media
, M_DEVBUF
);