1 /* $NetBSD: if_tlp_ap.c,v 1.10 2008/04/28 20:23:30 martin Exp $ */
4 * Copyright (c) 2000 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: if_tlp_ap.c,v 1.10 2008/04/28 20:23:30 martin Exp $");
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/malloc.h>
40 #include <sys/socket.h>
41 #include <sys/syslog.h>
42 #include <sys/systm.h>
45 #include <net/if_dl.h>
46 #include <net/if_media.h>
47 #include <net/if_ether.h>
49 #include <machine/bus.h>
50 #include <machine/intr.h>
52 #include <mips/cache.h>
54 #include <dev/mii/miivar.h>
55 #include <dev/mii/mii_bitbang.h>
57 #include <dev/ic/tulipreg.h>
58 #include <dev/ic/tulipvar.h>
60 #include <newsmips/apbus/apbusvar.h>
62 #define TLP_AP_ROM 0x00000000 /* AProm entry address */
63 #define TLP_AP_CFG 0x00040000 /* PCI configuration registers */
64 #define TLP_AP_CFG_CFID 0x00 /* Identification */
65 #define TLP_AP_CFG_CFCS 0x04 /* Command and status */
66 #define TLP_AP_CFG_CFRV 0x08 /* Revision */
67 #define TLP_AP_CFG_CFLT 0x0c /* Latency timer */
68 #define TLP_AP_CFG_CBIO 0x10 /* Base I/O address */
69 #define TLP_AP_CFG_CBMA 0x14 /* Base memory address */
70 #define TLP_AP_CFG_CFIT 0x3c /* Interrupt */
71 #define TLP_AP_CSR 0x00080000 /* CSR base address */
72 #define TLP_AP_RST 0x00100000 /* Board Reset */
75 struct tulip_ap_softc
{
76 struct tulip_softc sc_tulip
; /* real Tulip softc */
77 bus_space_tag_t sc_cfst
;
78 bus_space_handle_t sc_cfsh
;
81 static int tlp_ap_match(device_t
, cfdata_t
, void *);
82 static void tlp_ap_attach(device_t
, device_t
, void *);
84 CFATTACH_DECL_NEW(tlp_ap
, sizeof(struct tulip_ap_softc
),
85 tlp_ap_match
, tlp_ap_attach
, NULL
, NULL
);
87 static void tlp_ap_preinit(struct tulip_softc
*);
88 static void tlp_ap_tmsw_init(struct tulip_softc
*);
89 static void tlp_ap_getmedia(struct tulip_softc
*, struct ifmediareq
*);
90 static int tlp_ap_setmedia(struct tulip_softc
*);
92 const struct tulip_mediasw tlp_ap_mediasw
= {
93 tlp_ap_tmsw_init
, tlp_ap_getmedia
, tlp_ap_setmedia
97 tlp_ap_match(device_t parent
, cfdata_t cf
, void *aux
)
99 struct apbus_attach_args
*apa
= aux
;
101 if (strcmp(apa
->apa_name
, "cbasetx") != 0)
108 * Install interface into kernel networking data structures
111 tlp_ap_attach(device_t parent
, device_t self
, void *aux
)
113 struct tulip_ap_softc
*psc
= device_private(self
);
114 struct tulip_softc
*sc
= &psc
->sc_tulip
;
115 struct apbus_attach_args
*apa
= aux
;
116 uint8_t enaddr
[ETHER_ADDR_LEN
];
122 aprint_normal(" slot%d addr 0x%lx", apa
->apa_slotno
, apa
->apa_hwbase
);
124 /* PCI configuration register */
126 psc
->sc_cfsh
= apa
->apa_hwbase
+ TLP_AP_CFG
;
127 sc
->sc_devno
= apa
->apa_slotno
;
128 sc
->sc_rev
= bus_space_read_4(psc
->sc_cfst
, psc
->sc_cfsh
,
130 switch (bus_space_read_4(psc
->sc_cfst
, psc
->sc_cfsh
, TLP_AP_CFG_CFID
)) {
132 if (sc
->sc_rev
>= 0x20)
133 sc
->sc_chip
= TULIP_CHIP_21140A
;
135 sc
->sc_chip
= TULIP_CHIP_21140
;
138 aprint_error(": unable to handle your board\n");
142 aprint_normal(": %s Ethernet, pass %d.%d\n",
143 tlp_chip_names
[sc
->sc_chip
],
144 (sc
->sc_rev
>> 4) & 0xf, sc
->sc_rev
& 0xf);
148 sc
->sc_sh
= apa
->apa_hwbase
+ TLP_AP_CSR
;
149 sc
->sc_dmat
= apbus_dmatag_init(apa
);
150 if (sc
->sc_dmat
== NULL
) {
151 aprint_error_dev(self
, "cannot allocate memory\n");
156 * Initialize bus specific parameters.
158 if (mips_sdcache_line_size
> 0)
159 sc
->sc_cacheline
= mips_sdcache_line_size
/ 4;
160 else if (mips_pdcache_line_size
> 0)
161 sc
->sc_cacheline
= mips_pdcache_line_size
/ 4;
163 sc
->sc_cacheline
= 4;
164 sc
->sc_maxburst
= sc
->sc_cacheline
; /* XXX */
166 sc
->sc_flags
|= TULIPF_DBO
| TULIPF_BLE
; /* Big Endian BUS */
167 sc
->sc_flags
|= TULIPF_ENABLED
; /* No Power Mgmt */
172 bus_space_write_4(0, apa
->apa_hwbase
+ TLP_AP_RST
, 0, 1);
176 * Initialize PCI configuration register
178 bus_space_write_4(psc
->sc_cfst
, psc
->sc_cfsh
,
179 TLP_AP_CFG_CFCS
, 0x00000005); /* Master, IO */
180 bus_space_write_4(psc
->sc_cfst
, psc
->sc_cfsh
,
181 TLP_AP_CFG_CFLT
, 0x00000100);
182 bus_space_write_4(psc
->sc_cfst
, psc
->sc_cfsh
,
183 TLP_AP_CFG_CBIO
, MIPS_KSEG1_TO_PHYS(sc
->sc_sh
));
184 bus_space_write_4(psc
->sc_cfst
, psc
->sc_cfsh
,
185 TLP_AP_CFG_CFIT
, 0x00000101);
188 * Initialize general purpose port register.
190 TULIP_WRITE(sc
, CSR_GPP
, GPP_GPC
| 0xc0); /* read */
191 TULIP_WRITE(sc
, CSR_GPP
, 0x40); /* dipsw port on */
192 i
= TULIP_READ(sc
, CSR_GPP
) & GPP_MD
; /* dipsw contents */
193 TULIP_WRITE(sc
, CSR_GPP
, 0xc0); /* dipsw port off */
194 TULIP_WRITE(sc
, CSR_GPP
, GPP_GPC
| 0xcf); /* read write */
195 if (sc
->sc_maxburst
== 16) {
196 TULIP_WRITE(sc
, CSR_GPP
, 0x8f); /* 16word burst */
197 TULIP_WRITE(sc
, CSR_GPP
, 0xcf);
199 TULIP_WRITE(sc
, CSR_GPP
, 0x8e); /* 8word burst */
200 TULIP_WRITE(sc
, CSR_GPP
, 0xce);
202 TULIP_WRITE(sc
, CSR_GPP
, GPP_GPC
| 0xcf); /* read write */
203 TULIP_WRITE(sc
, CSR_GPP
, 0xc3); /* mask abort/DMA err */
204 TULIP_WRITE(sc
, CSR_GPP
, 0xcf); /* mask abort/DMA err */
206 if (tlp_read_srom(sc
) == 0) {
207 aprint_error_dev(self
, "srom read failed\n");
208 free(sc
->sc_dmat
, M_DEVBUF
);
211 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++)
212 enaddr
[i
] = sc
->sc_srom
[0x11 + i
* 2];
214 sc
->sc_mediasw
= &tlp_ap_mediasw
;
217 * Finish off the attach.
219 tlp_attach(sc
, enaddr
);
221 intrmask
= SLOTTOMASK(apa
->apa_slotno
);
222 apbus_intr_establish(0, /* interrupt level (0 or 1) */
225 tlp_intr
, sc
, apa
->apa_name
, apa
->apa_ctlnum
);
229 tlp_ap_preinit(struct tulip_softc
*sc
)
232 sc
->sc_opmode
|= OPMODE_MBO
| OPMODE_SCR
| OPMODE_PCS
| OPMODE_HBD
|
234 TULIP_WRITE(sc
, CSR_OPMODE
, sc
->sc_opmode
);
238 tlp_ap_tmsw_init(struct tulip_softc
*sc
)
240 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
242 sc
->sc_preinit
= tlp_ap_preinit
;
244 sc
->sc_mii
.mii_ifp
= ifp
;
245 sc
->sc_mii
.mii_readreg
= NULL
;
246 sc
->sc_mii
.mii_writereg
= NULL
;
247 sc
->sc_mii
.mii_statchg
= sc
->sc_statchg
;
248 ifmedia_init(&sc
->sc_mii
.mii_media
, 0, tlp_mediachange
,
250 ifmedia_add(&sc
->sc_mii
.mii_media
, IFM_ETHER
|IFM_100_TX
, 0, NULL
);
251 ifmedia_add(&sc
->sc_mii
.mii_media
, IFM_ETHER
|IFM_100_TX
|IFM_FDX
, 0,
253 ifmedia_set(&sc
->sc_mii
.mii_media
, IFM_ETHER
|IFM_100_TX
);
257 tlp_ap_getmedia(struct tulip_softc
*sc
, struct ifmediareq
*ifmr
)
259 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
261 ifmr
->ifm_status
= IFM_AVALID
;
262 if (ifp
->if_flags
& IFF_RUNNING
)
263 ifmr
->ifm_status
|= IFM_ACTIVE
;
264 ifmr
->ifm_active
= sc
->sc_mii
.mii_media_active
;
268 tlp_ap_setmedia(struct tulip_softc
*sc
)
270 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
272 sc
->sc_mii
.mii_media_active
= sc
->sc_mii
.mii_media
.ifm_cur
->ifm_media
;
274 if (ifp
->if_flags
& IFF_UP
)
275 tlp_idle(sc
, OPMODE_ST
|OPMODE_SR
);
276 if (sc
->sc_mii
.mii_media_active
& IFM_FDX
)
277 sc
->sc_opmode
|= OPMODE_FD
;
279 sc
->sc_opmode
&= ~OPMODE_FD
;
280 if (ifp
->if_flags
& IFF_UP
)
281 TULIP_WRITE(sc
, CSR_OPMODE
, sc
->sc_opmode
);