Bug Summary

File:dev/pcmcia/if_xe.c
Warning:line 740, column 2
Value stored to 'rsr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_xe.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pcmcia/if_xe.c
1/* $OpenBSD: if_xe.c,v 1.61 2021/03/07 06:20:09 jsg Exp $ */
2
3/*
4 * Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niklas Hallqvist,
18 * C Stone and Job de Haas.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * A driver for Xircom ethernet PC-cards.
36 *
37 * The driver has been inspired by the xirc2ps_cs.c driver found in Linux'
38 * PCMCIA package written by Werner Koch <werner.koch@guug.de>:
39 * [xirc2ps_cs.c wk 14.04.97] (1.31 1998/12/09 19:32:55)
40 * I will note that no code was used verbatim from that driver as it is under
41 * the much too strong GNU General Public License, it was only used as a
42 * "specification" of sorts.
43 * Other inspirations have been if_fxp.c, if_ep_pcmcia.c and elink3.c as
44 * they were found in OpenBSD 2.4.
45 */
46
47#include "bpfilter.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/device.h>
52#include <sys/ioctl.h>
53#include <sys/mbuf.h>
54#include <sys/malloc.h>
55#include <sys/kernel.h>
56#include <sys/socket.h>
57#include <sys/syslog.h>
58
59#include <net/if.h>
60#include <net/if_media.h>
61
62#include <netinet/in.h>
63#include <netinet/if_ether.h>
64
65#if NBPFILTER1 > 0
66#include <net/bpf.h>
67#endif
68
69/*
70 * Maximum number of bytes to read per interrupt. Linux recommends
71 * somewhere between 2000-22000.
72 * XXX This is currently a hard maximum.
73 */
74#define MAX_BYTES_INTR12000 12000
75
76#include <dev/mii/miivar.h>
77
78#include <dev/pcmcia/pcmciareg.h>
79#include <dev/pcmcia/pcmciavar.h>
80#include <dev/pcmcia/pcmciadevs.h>
81#include <dev/pcmcia/if_xereg.h>
82
83#ifdef __GNUC__4
84#define INLINE__inline __inline
85#else
86#define INLINE__inline
87#endif /* __GNUC__ */
88
89#ifdef XEDEBUG
90
91#define XED_CONFIG 0x1
92#define XED_MII 0x2
93#define XED_INTR 0x4
94#define XED_FIFO 0x8
95
96#ifndef XEDEBUG_DEF
97#define XEDEBUG_DEF (XED_CONFIG|XED_INTR)
98#endif /* XEDEBUG_DEF */
99
100int xedebug = XEDEBUG_DEF;
101
102#define DPRINTF(cat, x)(void)0 if (xedebug & (cat)) printf x
103
104#else /* XEDEBUG */
105#define DPRINTF(cat, x)(void)0 (void)0
106#endif /* XEDEBUG */
107
108int xe_pcmcia_match(struct device *, void *, void *);
109void xe_pcmcia_attach(struct device *, struct device *, void *);
110int xe_pcmcia_detach(struct device *, int);
111int xe_pcmcia_activate(struct device *, int);
112
113/*
114 * In case this chipset ever turns up out of pcmcia attachments (very
115 * unlikely) do the driver splitup.
116 */
117struct xe_softc {
118 struct device sc_dev; /* Generic device info */
119 u_int32_t sc_flags; /* Misc. flags */
120 void *sc_ih; /* Interrupt handler */
121 struct arpcom sc_arpcom; /* Ethernet common part */
122 struct ifmedia sc_media; /* Media control */
123 struct mii_data sc_mii; /* MII media information */
124 int sc_all_mcasts; /* Receive all multicasts */
125 bus_space_tag_t sc_bst; /* Bus cookie */
126 bus_space_handle_t sc_bsh; /* Bus I/O handle */
127 bus_size_t sc_offset; /* Offset of registers */
128 u_int8_t sc_rev; /* Chip revision */
129};
130
131#define XEF_MOHAWK0x001 0x001
132#define XEF_DINGO0x002 0x002
133#define XEF_MODEM0x004 0x004
134#define XEF_UNSUPPORTED0x008 0x008
135#define XEF_CE0x010 0x010
136#define XEF_CE20x020 0x020
137#define XEF_CE30x040 0x040
138#define XEF_CE330x080 0x080
139#define XEF_CE560x100 0x100
140
141struct xe_pcmcia_softc {
142 struct xe_softc sc_xe; /* Generic device info */
143 struct pcmcia_mem_handle sc_pcmh; /* PCMCIA memspace info */
144 int sc_mem_window; /* mem window */
145 struct pcmcia_io_handle sc_pcioh; /* iospace info */
146 int sc_io_window; /* io window info */
147 struct pcmcia_function *sc_pf; /* PCMCIA function */
148};
149
150/* Autoconfig definition of driver back-end */
151struct cfdriver xe_cd = {
152 NULL((void *)0), "xe", DV_IFNET
153};
154
155struct cfattach xe_pcmcia_ca = {
156 sizeof (struct xe_pcmcia_softc), xe_pcmcia_match, xe_pcmcia_attach,
157 xe_pcmcia_detach, xe_pcmcia_activate
158};
159
160void xe_cycle_power(struct xe_softc *);
161void xe_full_reset(struct xe_softc *);
162void xe_init(struct xe_softc *);
163int xe_intr(void *);
164int xe_ioctl(struct ifnet *, u_long, caddr_t);
165int xe_mdi_read(struct device *, int, int);
166void xe_mdi_write(struct device *, int, int, int);
167int xe_mediachange(struct ifnet *);
168void xe_mediastatus(struct ifnet *, struct ifmediareq *);
169int xe_pcmcia_funce_enaddr(struct device *, u_int8_t *);
170u_int32_t xe_pcmcia_interpret_manfid(struct device *);
171int xe_pcmcia_lan_nid_ciscallback(struct pcmcia_tuple *, void *);
172int xe_pcmcia_manfid_ciscallback(struct pcmcia_tuple *, void *);
173u_int16_t xe_get(struct xe_softc *);
174void xe_reset(struct xe_softc *);
175void xe_set_address(struct xe_softc *);
176void xe_start(struct ifnet *);
177void xe_statchg(struct device *);
178void xe_stop(struct xe_softc *);
179void xe_watchdog(struct ifnet *);
180#ifdef XEDEBUG
181void xe_reg_dump(struct xe_softc *);
182#endif /* XEDEBUG */
183
184int
185xe_pcmcia_match(struct device *parent, void *match, void *aux)
186{
187 struct pcmcia_attach_args *pa = aux;
188
189 if (pa->pf->function != PCMCIA_FUNCTION_NETWORK6)
190 return (0);
191
192 switch (pa->manufacturer) {
193 case PCMCIA_VENDOR_COMPAQ0x0138:
194 case PCMCIA_VENDOR_COMPAQ20x0183:
195 return (0);
196
197 case PCMCIA_VENDOR_INTEL0x0089:
198 case PCMCIA_VENDOR_XIRCOM0x0105:
199 /* XXX Per-productid checking here. */
200 return (1);
201
202 default:
203 return (0);
204 }
205}
206
207void
208xe_pcmcia_attach(struct device *parent, struct device *self, void *aux)
209{
210 struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)self;
211 struct xe_softc *sc = &psc->sc_xe;
212 struct pcmcia_attach_args *pa = aux;
213 struct pcmcia_function *pf = pa->pf;
214 struct pcmcia_config_entry *cfe = NULL((void *)0);
215 struct ifnet *ifp;
216 u_int8_t myla[ETHER_ADDR_LEN6], *enaddr = NULL((void *)0);
217 int state = 0;
218 struct pcmcia_mem_handle pcmh;
219 int ccr_window;
220 bus_size_t ccr_offset;
221 const char *intrstr;
222
223 psc->sc_pf = pf;
224
225#if 0
226 /* Figure out what card we are. */
227 sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
228#endif
229 if (sc->sc_flags & XEF_UNSUPPORTED0x008) {
230 printf(": card unsupported\n");
231 goto bad;
232 }
233
234 /* Tell the pcmcia framework where the CCR is. */
235 pf->ccr_base = 0x800;
236 pf->ccr_mask = 0x67;
237
238 /* Fake a cfe. */
239 SIMPLEQ_FIRST(&pa->pf->cfe_head)((&pa->pf->cfe_head)->sqh_first) = cfe = (struct pcmcia_config_entry *)
240 malloc(sizeof *cfe, M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
241 if (!cfe) {
242 printf(": function enable failed\n");
243 return;
244 }
245
246 /*
247 * XXX Use preprocessor symbols instead.
248 * Enable ethernet & its interrupts, wiring them to -INT
249 * No I/O base.
250 */
251 cfe->number = 0x5;
252 cfe->flags = 0; /* XXX Check! */
253 cfe->iftype = PCMCIA_IFTYPE_IO1;
254 cfe->num_iospace = 0;
255 cfe->num_memspace = 0;
256 cfe->irqmask = 0x8eb0;
257
258 /* Enable the card. */
259 pcmcia_function_init(pa->pf, cfe);
260 if (pcmcia_function_enable(pa->pf)) {
261 printf(": function enable failed\n");
262 goto bad;
263 }
264
265 state++;
266
267 if (pcmcia_io_alloc(pa->pf, 0, 16, 16, &psc->sc_pcioh)(((*((pa->pf)->sc->pct)->io_alloc)((pa->pf->
sc->pch), ((0)), ((16)), ((16)), ((&psc->sc_pcioh))
)))
) {
268 printf(": io allocation failed\n");
269 goto bad;
270 }
271
272 state++;
273
274 if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO162, 0, 16, &psc->sc_pcioh,
275 &psc->sc_io_window)) {
276 printf(": can't map io space\n");
277 goto bad;
278 }
279 sc->sc_bst = psc->sc_pcioh.iot;
280 sc->sc_bsh = psc->sc_pcioh.ioh;
281 sc->sc_offset = 0;
282
283 printf(" port 0x%lx/%d", psc->sc_pcioh.addr, 16);
284
285#if 0
286 if (pcmcia_mem_alloc(pf, 16, &psc->sc_pcmh)(((*((pf)->sc->pct)->mem_alloc)(((pf)->sc->pch
), ((16)), ((&psc->sc_pcmh)))))
) {
287 printf(": pcmcia memory allocation failed\n");
288 goto bad;
289 }
290 state++;
291
292 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0x300, 16, &psc->sc_pcmh,(((*((pf)->sc->pct)->mem_map)(((pf)->sc->pch),
((1)), ((0x300)), ((16)), ((&psc->sc_pcmh)), ((&sc
->sc_offset)), ((&psc->sc_mem_window)))))
293 &sc->sc_offset, &psc->sc_mem_window)(((*((pf)->sc->pct)->mem_map)(((pf)->sc->pch),
((1)), ((0x300)), ((16)), ((&psc->sc_pcmh)), ((&sc
->sc_offset)), ((&psc->sc_mem_window)))))
) {
294 printf(": pcmcia memory mapping failed\n");
295 goto bad;
296 }
297
298 sc->sc_bst = psc->sc_pcmh.memt;
299 sc->sc_bsh = psc->sc_pcmh.memh;
300#endif
301
302 /* Figure out what card we are. */
303 sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
304
305 /*
306 * Configuration as advised by DINGO documentation.
307 * We only know about this flag after the manfid interpretation.
308 * Dingo has some extra configuration registers in the CCR space.
309 */
310 if (sc->sc_flags & XEF_DINGO0x002) {
311 if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE_DINGO, &pcmh)(((*((pf)->sc->pct)->mem_alloc)(((pf)->sc->pch
), ((0x54)), ((&pcmh)))))
) {
312 DPRINTF(XED_CONFIG, ("bad mem alloc\n"))(void)0;
313 goto bad;
314 }
315
316 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,(((*((pf)->sc->pct)->mem_map)(((pf)->sc->pch),
((1)), ((pf->ccr_base)), ((0x54)), ((&pcmh)), ((&
ccr_offset)), ((&ccr_window)))))
317 PCMCIA_CCR_SIZE_DINGO, &pcmh, &ccr_offset,(((*((pf)->sc->pct)->mem_map)(((pf)->sc->pch),
((1)), ((pf->ccr_base)), ((0x54)), ((&pcmh)), ((&
ccr_offset)), ((&ccr_window)))))
318 &ccr_window)(((*((pf)->sc->pct)->mem_map)(((pf)->sc->pch),
((1)), ((pf->ccr_base)), ((0x54)), ((&pcmh)), ((&
ccr_offset)), ((&ccr_window)))))
) {
319 DPRINTF(XED_CONFIG, ("bad mem map\n"))(void)0;
320 pcmcia_mem_free(pf, &pcmh)(((*((pf)->sc->pct)->mem_free)(((pf)->sc->pch)
, ((&pcmh)))))
;
321 goto bad;
322 }
323
324 bus_space_write_1(pcmh.memt, pcmh.memh,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x20), (0x01
)))
325 ccr_offset + PCMCIA_CCR_DCOR0, PCMCIA_CCR_DCOR0_SFINT)((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x20), (0x01
)))
;
326 bus_space_write_1(pcmh.memt, pcmh.memh,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x22), (0x08
| 0x04)))
327 ccr_offset + PCMCIA_CCR_DCOR1,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x22), (0x08
| 0x04)))
328 PCMCIA_CCR_DCOR1_FORCE_LEVIREQ | PCMCIA_CCR_DCOR1_D6)((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x22), (0x08
| 0x04)))
;
329 bus_space_write_1(pcmh.memt, pcmh.memh,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x24), (0
)))
330 ccr_offset + PCMCIA_CCR_DCOR2, 0)((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x24), (0
)))
;
331 bus_space_write_1(pcmh.memt, pcmh.memh,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x26), (0
)))
332 ccr_offset + PCMCIA_CCR_DCOR3, 0)((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x26), (0
)))
;
333 bus_space_write_1(pcmh.memt, pcmh.memh,((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x28), (0
)))
334 ccr_offset + PCMCIA_CCR_DCOR4, 0)((pcmh.memt)->write_1((pcmh.memh), (ccr_offset + 0x28), (0
)))
;
335
336 /* We don't need them anymore and can free them (I think). */
337 pcmcia_mem_unmap(pf, ccr_window)(((*((pf)->sc->pct)->mem_unmap)(((pf)->sc->pch
), ((ccr_window)))))
;
338 pcmcia_mem_free(pf, &pcmh)(((*((pf)->sc->pct)->mem_free)(((pf)->sc->pch)
, ((&pcmh)))))
;
339 }
340
341 /*
342 * Try to get the ethernet address from FUNCE/LAN_NID tuple.
343 */
344 if (xe_pcmcia_funce_enaddr(parent, myla))
345 enaddr = myla;
346 ifp = &sc->sc_arpcom.ac_if;
347 if (enaddr)
348 bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6);
349 else {
350 printf(", unable to get ethernet address\n");
351 goto bad;
352 }
353
354 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ16);
355 ifp->if_softc = sc;
356 ifp->if_flags =
357 IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
358 ifp->if_ioctl = xe_ioctl;
359 ifp->if_start = xe_start;
360 ifp->if_watchdog = xe_watchdog;
361
362 /* Establish the interrupt. */
363 sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET0x7, xe_intr, sc,
364 sc->sc_dev.dv_xname);
365 if (sc->sc_ih == NULL((void *)0)) {
366 printf(", couldn't establish interrupt\n");
367 goto bad;
368 }
369 intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
370 printf("%s%s: address %s\n", *intrstr ? ", " : "", intrstr,
371 ether_sprintf(sc->sc_arpcom.ac_enaddr));
372
373 /* Reset and initialize the card. */
374 xe_full_reset(sc);
375
376 /* Initialize our media structures and probe the phy. */
377 sc->sc_mii.mii_ifp = ifp;
378 sc->sc_mii.mii_readreg = xe_mdi_read;
379 sc->sc_mii.mii_writereg = xe_mdi_write;
380 sc->sc_mii.mii_statchg = xe_statchg;
381 ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK0xff00000000000000ULL, xe_mediachange,
382 xe_mediastatus);
383 DPRINTF(XED_MII | XED_CONFIG,(void)0
384 ("bmsr %x\n", xe_mdi_read(&sc->sc_dev, 0, 1)))(void)0;
385 mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY-1, MII_OFFSET_ANY-1,
386 0);
387 if (LIST_FIRST(&sc->sc_mii.mii_phys)((&sc->sc_mii.mii_phys)->lh_first) == NULL((void *)0))
388 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL, 0,
389 NULL((void *)0));
390 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
391
392 /*
393 * Attach the interface.
394 */
395 if_attach(ifp);
396 ether_ifattach(ifp);
397
398 /*
399 * Reset and initialize the card again for DINGO (as found in Linux
400 * driver). Without this Dingo will get a watchdog timeout the first
401 * time. The ugly media tickling seems to be necessary for getting
402 * autonegotiation to work too.
403 */
404 if (sc->sc_flags & XEF_DINGO0x002) {
405 xe_full_reset(sc);
406 xe_init(sc);
407 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
408 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL);
409 xe_stop(sc);
410 }
411 return;
412
413bad:
414 if (state > 2)
415 pcmcia_io_unmap(pf, psc->sc_io_window)(((*((pf)->sc->pct)->io_unmap)(((pf)->sc->pch)
, ((psc->sc_io_window)))))
;
416 if (state > 1)
417 pcmcia_io_free(pf, &psc->sc_pcioh)(((*((pf)->sc->pct)->io_free)(((pf)->sc->pch),
((&psc->sc_pcioh)))))
;
418 if (state > 0)
419 pcmcia_function_disable(pa->pf);
420 free(cfe, M_DEVBUF2, 0);
421}
422
423int
424xe_pcmcia_detach(struct device *dev, int flags)
425{
426 struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)dev;
427 struct xe_softc *sc = &psc->sc_xe;
428 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
429 int rv = 0;
430
431 mii_detach(&sc->sc_mii, MII_PHY_ANY-1, MII_OFFSET_ANY-1);
432 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY((uint64_t) -1));
433
434 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window)(((*((psc->sc_pf)->sc->pct)->io_unmap)(((psc->
sc_pf)->sc->pch), ((psc->sc_io_window)))))
;
435 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh)(((*((psc->sc_pf)->sc->pct)->io_free)(((psc->sc_pf
)->sc->pch), ((&psc->sc_pcioh)))))
;
436
437 ether_ifdetach(ifp);
438 if_detach(ifp);
439
440 return (rv);
441}
442
443int
444xe_pcmcia_activate(struct device *dev, int act)
445{
446 struct xe_pcmcia_softc *sc = (struct xe_pcmcia_softc *)dev;
447 struct ifnet *ifp = &sc->sc_xe.sc_arpcom.ac_if;
448
449 switch (act) {
450 case DVACT_SUSPEND3:
451 if (ifp->if_flags & IFF_RUNNING0x40)
452 xe_stop(&sc->sc_xe);
453 ifp->if_flags &= ~IFF_RUNNING0x40;
454 if (sc->sc_xe.sc_ih)
455 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih);
456 sc->sc_xe.sc_ih = NULL((void *)0);
457 pcmcia_function_disable(sc->sc_pf);
458 break;
459 case DVACT_RESUME4:
460 pcmcia_function_enable(sc->sc_pf);
461 sc->sc_xe.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET0x7,
462 xe_intr, sc, sc->sc_xe.sc_dev.dv_xname);
463 /* XXX this is a ridiculous */
464 xe_reset(&sc->sc_xe);
465 if ((ifp->if_flags & IFF_UP0x1) == 0)
466 xe_stop(&sc->sc_xe);
467 break;
468 case DVACT_DEACTIVATE1:
469 ifp->if_timer = 0;
470 ifp->if_flags &= ~IFF_RUNNING0x40;
471 if (sc->sc_xe.sc_ih)
472 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih);
473 sc->sc_xe.sc_ih = NULL((void *)0);
474 pcmcia_function_disable(sc->sc_pf);
475 break;
476 }
477 return (0);
478}
479
480/*
481 * XXX These two functions might be OK to factor out into pcmcia.c since
482 * if_sm_pcmcia.c uses similar ones.
483 */
484int
485xe_pcmcia_funce_enaddr(struct device *parent, u_int8_t *myla)
486{
487 /* XXX The Linux driver has more ways to do this in case of failure. */
488 return (pcmcia_scan_cis(parent, xe_pcmcia_lan_nid_ciscallback, myla));
489}
490
491int
492xe_pcmcia_lan_nid_ciscallback(struct pcmcia_tuple *tuple, void *arg)
493{
494 u_int8_t *myla = arg;
495 int i;
496
497 if (tuple->code == PCMCIA_CISTPL_FUNCE0x22) {
498 if (tuple->length < 2)
499 return (0);
500
501 switch (pcmcia_tuple_read_1(tuple, 0)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(0)))))) {
502 case PCMCIA_TPLFE_TYPE_LAN_NID0x04:
503 if (pcmcia_tuple_read_1(tuple, 1)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(1))))) != ETHER_ADDR_LEN6)
504 return (0);
505 break;
506
507 case 0x02:
508 /*
509 * Not sure about this, I don't have a CE2
510 * that puts the ethernet addr here.
511 */
512 if (pcmcia_tuple_read_1(tuple, 1)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(1))))) != 13)
513 return (0);
514 break;
515
516 default:
517 return (0);
518 }
519
520 for (i = 0; i < ETHER_ADDR_LEN6; i++)
521 myla[i] = pcmcia_tuple_read_1(tuple, i + 2)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(i + 2)))));
522 return (1);
523 }
524
525 /* Yet another spot where this might be. */
526 if (tuple->code == 0x89) {
527 pcmcia_tuple_read_1(tuple, 1)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(1)))));
528 for (i = 0; i < ETHER_ADDR_LEN6; i++)
529 myla[i] = pcmcia_tuple_read_1(tuple, i + 2)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(i + 2)))));
530 return (1);
531 }
532 return (0);
533}
534
535u_int32_t
536xe_pcmcia_interpret_manfid(struct device *parent)
537{
538 u_int32_t flags = 0;
539 struct pcmcia_softc *psc = (struct pcmcia_softc *)parent;
540 char *tptr;
541
542 if (!pcmcia_scan_cis(parent, xe_pcmcia_manfid_ciscallback, &flags))
543 return (XEF_UNSUPPORTED0x008);
544
545 if (flags & XEF_CE0x010) {
546 tptr = memchr(psc->card.cis1_info[2], 'C',
547 strlen(psc->card.cis1_info[2]));
548 /* XXX not sure if other CE2s hide "CE2" in different places */
549 if (tptr && *(tptr + 1) == 'E' && *(tptr + 2) == '2') {
550 flags ^= (XEF_CE0x010 | XEF_UNSUPPORTED0x008);
551 flags |= XEF_CE20x020;
552 }
553 }
554 return (flags);
555}
556
557int
558xe_pcmcia_manfid_ciscallback(struct pcmcia_tuple *tuple, void *arg)
559{
560 u_int32_t *flagsp = arg;
561 u_int8_t media, product;
562
563 if (tuple->code == PCMCIA_CISTPL_MANFID0x20) {
564 if (tuple->length < 2)
565 return (0);
566
567 media = pcmcia_tuple_read_1(tuple, 3)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(3)))));
568 product = pcmcia_tuple_read_1(tuple, 4)(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(4)))));
569
570 if (!(product & XEPROD_CREDITCARD0x40) ||
571 !(media & XEMEDIA_ETHER0x01)) {
572 *flagsp |= XEF_UNSUPPORTED0x008;
573 return (1);
574 }
575
576 if (media & XEMEDIA_MODEM0x10)
577 *flagsp |= XEF_MODEM0x004;
578
579 switch (product & XEPROD_IDMASK0x0f) {
580 case 1:
581 /* XXX Can be CE2 too (we double-check later). */
582 *flagsp |= XEF_CE0x010 | XEF_UNSUPPORTED0x008;
583 break;
584 case 2:
585 *flagsp |= XEF_CE20x020;
586 break;
587 case 3:
588 if (!(*flagsp & XEF_MODEM0x004))
589 *flagsp |= XEF_MOHAWK0x001;
590 *flagsp |= XEF_CE30x040;
591 break;
592 case 4:
593 *flagsp |= XEF_CE330x080;
594 break;
595 case 5:
596 *flagsp |= XEF_CE560x100 | XEF_MOHAWK0x001;
597 break;
598 case 6:
599 case 7:
600 *flagsp |= XEF_CE560x100 | XEF_MOHAWK0x001 | XEF_DINGO0x002;
601 break;
602 default:
603 *flagsp |= XEF_UNSUPPORTED0x008;
604 break;
605 }
606
607 return (1);
608 }
609 return (0);
610}
611
612int
613xe_intr(void *arg)
614{
615 struct xe_softc *sc = arg;
616 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
617 u_int8_t esr, rsr, isr, rx_status, savedpage;
618 u_int16_t tx_status, recvcount = 0, tempint;
619
620 ifp->if_timer = 0; /* turn watchdog timer off */
621
622 if (sc->sc_flags & XEF_MOHAWK0x001) {
623 /* Disable interrupt (Linux does it). */
624 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0)))
625 0)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0)))
;
626 }
627
628 savedpage =
629 bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + PR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x1)))
;
630
631 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
632 esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ESR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x0)))
;
633 isr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ISR0)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x6)))
;
634 rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0xc)))
;
635
636 /* Check to see if card has been ejected. */
637 if (isr == 0xff) {
638 printf("%s: interrupt for dead card\n", sc->sc_dev.dv_xname);
639 goto end;
640 }
641
642 PAGE(sc, 40)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((40))))
;
643 rx_status =
644 bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RXST0)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x9)))
;
645 tx_status =
646 bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + TXST0)((sc->sc_bst)->read_2((sc->sc_bsh), (sc->sc_offset
+ 0xb)))
;
647
648 /*
649 * XXX Linux writes to RXST0 and TXST* here. My CE2 works just fine
650 * without it, and I can't see an obvious reason for it.
651 */
652
653 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
654 while (esr & FULL_PKT_RCV0x01) {
655 if (!(rsr & RSR_RX_OK0x80))
656 break;
657
658 /* Compare bytes read this interrupt to hard maximum. */
659 if (recvcount > MAX_BYTES_INTR12000) {
660 DPRINTF(XED_INTR,(void)0
661 ("%s: too many bytes this interrupt\n",(void)0
662 sc->sc_dev.dv_xname))(void)0;
663 ifp->if_iqdropsif_data.ifi_iqdrops++;
664 /* Drop packet. */
665 bus_space_write_2(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->write_2((sc->sc_bsh), (sc->sc_offset
+ 0xc), (0x8000)))
666 sc->sc_offset + DO0, DO_SKIP_RX_PKT)((sc->sc_bst)->write_2((sc->sc_bsh), (sc->sc_offset
+ 0xc), (0x8000)))
;
667 }
668 tempint = xe_get(sc);
669 recvcount += tempint;
670 esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x0)))
671 sc->sc_offset + ESR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x0)))
;
672 rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0xc)))
673 sc->sc_offset + RSR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0xc)))
;
674 }
675
676 /* Packet too long? */
677 if (rsr & RSR_TOO_LONG0x04) {
678 ifp->if_ierrorsif_data.ifi_ierrors++;
679 DPRINTF(XED_INTR,(void)0
680 ("%s: packet too long\n", sc->sc_dev.dv_xname))(void)0;
681 }
682
683 /* CRC error? */
684 if (rsr & RSR_CRCERR0x20) {
685 ifp->if_ierrorsif_data.ifi_ierrors++;
686 DPRINTF(XED_INTR,(void)0
687 ("%s: CRC error detected\n", sc->sc_dev.dv_xname))(void)0;
688 }
689
690 /* Alignment error? */
691 if (rsr & RSR_ALIGNERR0x10) {
692 ifp->if_ierrorsif_data.ifi_ierrors++;
693 DPRINTF(XED_INTR,(void)0
694 ("%s: alignment error detected\n", sc->sc_dev.dv_xname))(void)0;
695 }
696
697 /* Check for rx overrun. */
698 if (rx_status & RX_OVERRUN0x10) {
699 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x20)))
700 CLR_RX_OVERRUN)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x20)))
;
701 DPRINTF(XED_INTR, ("overrun cleared\n"))(void)0;
702 }
703
704 /* Try to start more packets transmitting. */
705 if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0)
706 xe_start(ifp);
707
708 /* Detected excessive collisions? */
709 if (tx_status & EXCESSIVE_COLL0x02) {
710 DPRINTF(XED_INTR,(void)0
711 ("%s: excessive collisions\n", sc->sc_dev.dv_xname))(void)0;
712 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x40)))
713 RESTART_TX)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x40)))
;
714 ifp->if_oerrorsif_data.ifi_oerrors++;
715 }
716
717 if (tx_status & TX_ABORT0x40)
718 ifp->if_oerrorsif_data.ifi_oerrors++;
719
720end:
721 /* Reenable interrupts. */
722 PAGE(sc, savedpage)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((savedpage))))
;
723 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x04)))
724 ENABLE_INT)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0x04)))
;
725
726 return (1);
727}
728
729u_int16_t
730xe_get(struct xe_softc *sc)
731{
732 u_int8_t rsr;
733 struct mbuf *top, **mp, *m;
734 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
735 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
736 u_int16_t pktlen, len, recvcount = 0;
737 u_int8_t *data;
738
739 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
740 rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0xc)))
;
Value stored to 'rsr' is never read
741
742 pktlen =
743 bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RBC0)((sc->sc_bst)->read_2((sc->sc_bsh), (sc->sc_offset
+ 0xe)))
&
744 RBC_COUNT_MASK0x1fff;
745 if (pktlen == 0) {
746 /*
747 * XXX At least one CE2 sets RBC0 == 0 occasionally, and only
748 * when MPE is set. It is not known why.
749 */
750 return (0);
751 }
752 recvcount += pktlen;
753
754 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
755 if (m == NULL((void *)0))
756 return (recvcount);
757 m->m_pkthdrM_dat.MH.MH_pkthdr.len = pktlen;
758 len = MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr));
759 top = 0;
760 mp = &top;
761
762 while (pktlen > 0) {
763 if (top) {
764 MGET(m, M_DONTWAIT, MT_DATA)m = m_get((0x0002), (1));
765 if (m == NULL((void *)0)) {
766 m_freem(top);
767 return (recvcount);
768 }
769 len = MLEN(256 - sizeof(struct m_hdr));
770 }
771 if (pktlen >= MINCLSIZE(((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr)) + (256
- sizeof(struct m_hdr)) + 1)
) {
772 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
773 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
774 m_freem(m);
775 m_freem(top);
776 return (recvcount);
777 }
778 len = MCLBYTES(1 << 11);
779 }
780 if (!top) {
781 caddr_t newdata = (caddr_t)ALIGN(m->m_data +(((unsigned long)(m->m_hdr.mh_data + sizeof (struct ether_header
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1))
782 sizeof (struct ether_header))(((unsigned long)(m->m_hdr.mh_data + sizeof (struct ether_header
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1))
-
783 sizeof (struct ether_header);
784 len -= newdata - m->m_datam_hdr.mh_data;
785 m->m_datam_hdr.mh_data = newdata;
786 }
787 len = min(pktlen, len);
788
789 data = mtod(m, u_int8_t *)((u_int8_t *)((m)->m_hdr.mh_data));
790 if (len > 1) {
791 len &= ~1;
792 bus_space_read_raw_multi_2(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->read_multi_2((sc->sc_bsh), (sc->sc_offset
+ 0x4), (u_int16_t *)(data), (len) >> 1))
793 sc->sc_offset + EDP, data, len)((sc->sc_bst)->read_multi_2((sc->sc_bsh), (sc->sc_offset
+ 0x4), (u_int16_t *)(data), (len) >> 1))
;
794 } else
795 *data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x4)))
796 sc->sc_offset + EDP)((sc->sc_bst)->read_1((sc->sc_bsh), (sc->sc_offset
+ 0x4)))
;
797 m->m_lenm_hdr.mh_len = len;
798 pktlen -= len;
799 *mp = m;
800 mp = &m->m_nextm_hdr.mh_next;
801 }
802
803 /* Skip Rx packet. */
804 bus_space_write_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + DO0,((sc->sc_bst)->write_2((sc->sc_bsh), (sc->sc_offset
+ 0xc), (0x8000)))
805 DO_SKIP_RX_PKT)((sc->sc_bst)->write_2((sc->sc_bsh), (sc->sc_offset
+ 0xc), (0x8000)))
;
806
807 ml_enqueue(&ml, top);
808 if_input(ifp, &ml);
809
810 return (recvcount);
811}
812
813
814/*
815 * Serial management for the MII.
816 * The DELAY's below stem from the fact that the maximum frequency
817 * acceptable on the MDC pin is 2.5 MHz and fast processors can easily
818 * go much faster than that.
819 */
820
821/* Let the MII serial management be idle for one period. */
822static INLINE__inline void xe_mdi_idle(struct xe_softc *);
823static INLINE__inline void
824xe_mdi_idle(struct xe_softc *sc)
825{
826 bus_space_tag_t bst = sc->sc_bst;
827 bus_space_handle_t bsh = sc->sc_bsh;
828 bus_size_t offset = sc->sc_offset;
829
830 /* Drive MDC low... */
831 bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW)((bst)->write_1((bsh), (offset + 0xd), (0x04)));
832 DELAY(1)(*delay_func)(1);
833
834 /* and high again. */
835 bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH)((bst)->write_1((bsh), (offset + 0xd), ((0x04 | 0x01))));
836 DELAY(1)(*delay_func)(1);
837}
838
839/* Pulse out one bit of data. */
840static INLINE__inline void xe_mdi_pulse(struct xe_softc *, int);
841static INLINE__inline void
842xe_mdi_pulse(struct xe_softc *sc, int data)
843{
844 bus_space_tag_t bst = sc->sc_bst;
845 bus_space_handle_t bsh = sc->sc_bsh;
846 bus_size_t offset = sc->sc_offset;
847 u_int8_t bit = data ? MDIO_HIGH(0x08 | 0x02) : MDIO_LOW0x08;
848
849 /* First latch the data bit MDIO with clock bit MDC low...*/
850 bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_LOW)((bst)->write_1((bsh), (offset + 0xd), (bit | 0x04)));
851 DELAY(1)(*delay_func)(1);
852
853 /* then raise the clock again, preserving the data bit. */
854 bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_HIGH)((bst)->write_1((bsh), (offset + 0xd), (bit | (0x04 | 0x01
))))
;
855 DELAY(1)(*delay_func)(1);
856}
857
858/* Probe one bit of data. */
859static INLINE__inline int xe_mdi_probe(struct xe_softc *sc);
860static INLINE__inline int
861xe_mdi_probe(struct xe_softc *sc)
862{
863 bus_space_tag_t bst = sc->sc_bst;
864 bus_space_handle_t bsh = sc->sc_bsh;
865 bus_size_t offset = sc->sc_offset;
866 u_int8_t x;
867
868 /* Pull clock bit MDCK low... */
869 bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW)((bst)->write_1((bsh), (offset + 0xd), (0x04)));
870 DELAY(1)(*delay_func)(1);
871
872 /* Read data and drive clock high again. */
873 x = bus_space_read_1(bst, bsh, offset + GP2)((bst)->read_1((bsh), (offset + 0xd))) & MDIO0x20;
874 bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH)((bst)->write_1((bsh), (offset + 0xd), ((0x04 | 0x01))));
875 DELAY(1)(*delay_func)(1);
876
877 return (x);
878}
879
880/* Pulse out a sequence of data bits. */
881static INLINE__inline void xe_mdi_pulse_bits(struct xe_softc *, u_int32_t, int);
882static INLINE__inline void
883xe_mdi_pulse_bits(struct xe_softc *sc, u_int32_t data, int len)
884{
885 u_int32_t mask;
886
887 for (mask = 1 << (len - 1); mask; mask >>= 1)
888 xe_mdi_pulse(sc, data & mask);
889}
890
891/* Read a PHY register. */
892int
893xe_mdi_read(struct device *self, int phy, int reg)
894{
895 struct xe_softc *sc = (struct xe_softc *)self;
896 int i;
897 u_int32_t mask;
898 u_int32_t data = 0;
899
900 PAGE(sc, 2)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((2))))
;
901 for (i = 0; i < 32; i++) /* Synchronize. */
902 xe_mdi_pulse(sc, 1);
903 xe_mdi_pulse_bits(sc, 0x06, 4); /* Start + Read opcode */
904 xe_mdi_pulse_bits(sc, phy, 5); /* PHY address */
905 xe_mdi_pulse_bits(sc, reg, 5); /* PHY register */
906 xe_mdi_idle(sc); /* Turn around. */
907 xe_mdi_probe(sc); /* Drop initial zero bit. */
908
909 for (mask = 1 << 15; mask; mask >>= 1)
910 if (xe_mdi_probe(sc))
911 data |= mask;
912 xe_mdi_idle(sc);
913
914 DPRINTF(XED_MII,(void)0
915 ("xe_mdi_read: phy %d reg %d -> %x\n", phy, reg, data))(void)0;
916 return (data);
917}
918
919/* Write a PHY register. */
920void
921xe_mdi_write(struct device *self, int phy, int reg, int value)
922{
923 struct xe_softc *sc = (struct xe_softc *)self;
924 int i;
925
926 PAGE(sc, 2)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((2))))
;
927 for (i = 0; i < 32; i++) /* Synchronize. */
928 xe_mdi_pulse(sc, 1);
929 xe_mdi_pulse_bits(sc, 0x05, 4); /* Start + Write opcode */
930 xe_mdi_pulse_bits(sc, phy, 5); /* PHY address */
931 xe_mdi_pulse_bits(sc, reg, 5); /* PHY register */
932 xe_mdi_pulse_bits(sc, 0x02, 2); /* Turn around. */
933 xe_mdi_pulse_bits(sc, value, 16); /* Write the data */
934 xe_mdi_idle(sc); /* Idle away. */
935
936 DPRINTF(XED_MII,(void)0
937 ("xe_mdi_write: phy %d reg %d val %x\n", phy, reg, value))(void)0;
938}
939
940void
941xe_statchg(struct device *self)
942{
943}
944
945/*
946 * Change media according to request.
947 */
948int
949xe_mediachange(struct ifnet *ifp)
950{
951 if (ifp->if_flags & IFF_UP0x1)
952 xe_init(ifp->if_softc);
953 return (0);
954}
955
956/*
957 * Notify the world which media we're using.
958 */
959void
960xe_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
961{
962 struct xe_softc *sc = ifp->if_softc;
963
964 mii_pollstat(&sc->sc_mii);
965 ifmr->ifm_status = sc->sc_mii.mii_media_status;
966 ifmr->ifm_active = sc->sc_mii.mii_media_active;
967}
968
969void
970xe_reset(struct xe_softc *sc)
971{
972 int s;
973
974 s = splnet()splraise(0x7);
975 xe_stop(sc);
976 xe_full_reset(sc);
977 xe_init(sc);
978 splx(s)spllower(s);
979}
980
981void
982xe_watchdog(struct ifnet *ifp)
983{
984 struct xe_softc *sc = ifp->if_softc;
985
986 log(LOG_ERR3, "%s: device timeout\n", sc->sc_dev.dv_xname);
987 ++sc->sc_arpcom.ac_if.if_oerrorsif_data.ifi_oerrors;
988
989 xe_reset(sc);
990}
991
992void
993xe_stop(struct xe_softc *sc)
994{
995 /* Disable interrupts. */
996 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
997 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR, 0)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x0), (0)))
;
998
999 PAGE(sc, 1)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((1))))
;
1000 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + IMR0, 0)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0xc), (0)))
;
1001
1002 /* Power down, wait. */
1003 PAGE(sc, 4)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((4))))
;
1004 bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + GP1, 0)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0)))
;
1005 DELAY(40000)(*delay_func)(40000);
1006
1007 /* Cancel watchdog timer. */
1008 sc->sc_arpcom.ac_if.if_timer = 0;
1009}
1010
1011void
1012xe_init(struct xe_softc *sc)
1013{
1014 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1015 int s;
1016
1017 DPRINTF(XED_CONFIG, ("xe_init\n"))(void)0;
1018
1019 s = splnet()splraise(0x7);
1020
1021 xe_set_address(sc);
1022
1023 /* Set current media. */
1024 mii_mediachg(&sc->sc_mii);
1025
1026 ifp->if_flags |= IFF_RUNNING0x40;
1027 ifq_clr_oactive(&ifp->if_snd);
1028 splx(s)spllower(s);
1029}
1030
1031/*
1032 * Start outputting on the interface.
1033 * Always called as splnet().
1034 */
1035void
1036xe_start(struct ifnet *ifp)
1037{
1038 struct xe_softc *sc = ifp->if_softc;
1039 bus_space_tag_t bst = sc->sc_bst;
1040 bus_space_handle_t bsh = sc->sc_bsh;
1041 bus_size_t offset = sc->sc_offset;
1042 unsigned int s, len, pad = 0;
1043 struct mbuf *m0, *m;
1044 u_int16_t space;
1045
1046 /* Don't transmit if interface is busy or not running. */
1047 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
1048 return;
1049
1050 /* Peek at the next packet. */
1051 m0 = ifq_deq_begin(&ifp->if_snd);
1052 if (m0 == NULL((void *)0))
1053 return;
1054
1055 /* We need to use m->m_pkthdr.len, so require the header. */
1056 if (!(m0->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002))
1057 panic("xe_start: no header mbuf");
1058
1059 len = m0->m_pkthdrM_dat.MH.MH_pkthdr.len;
1060
1061 /* Pad to ETHER_MIN_LEN - ETHER_CRC_LEN. */
1062 if (len < ETHER_MIN_LEN64 - ETHER_CRC_LEN4)
1063 pad = ETHER_MIN_LEN64 - ETHER_CRC_LEN4 - len;
1064
1065 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
1066 space = bus_space_read_2(bst, bsh, offset + TSO0)((bst)->read_2((bsh), (offset + 0x8))) & 0x7fff;
1067 if (len + pad + 2 > space) {
1068 ifq_deq_rollback(&ifp->if_snd, m0);
1069 DPRINTF(XED_FIFO,(void)0
1070 ("%s: not enough space in output FIFO (%d > %d)\n",(void)0
1071 sc->sc_dev.dv_xname, len + pad + 2, space))(void)0;
1072 return;
1073 }
1074
1075 ifq_deq_commit(&ifp->if_snd, m0);
1076
1077#if NBPFILTER1 > 0
1078 if (ifp->if_bpf)
1079 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT(1 << 1));
1080#endif
1081
1082 /*
1083 * Do the output at splhigh() so that an interrupt from another device
1084 * won't cause a FIFO underrun.
1085 */
1086 s = splhigh()splraise(0xd);
1087
1088 bus_space_write_2(bst, bsh, offset + TSO2, (u_int16_t)len + pad + 2)((bst)->write_2((bsh), (offset + 0xa), ((u_int16_t)len + pad
+ 2)))
;
1089 bus_space_write_2(bst, bsh, offset + EDP, (u_int16_t)len + pad)((bst)->write_2((bsh), (offset + 0x4), ((u_int16_t)len + pad
)))
;
1090 for (m = m0; m; ) {
1091 if (m->m_lenm_hdr.mh_len > 1)
1092 bus_space_write_raw_multi_2(bst, bsh, offset + EDP,((bst)->write_multi_2((bsh), (offset + 0x4), (const u_int16_t
*)(((u_int8_t *)((m)->m_hdr.mh_data))), (m->m_hdr.mh_len
& ~1) >> 1))
1093 mtod(m, u_int8_t *), m->m_len & ~1)((bst)->write_multi_2((bsh), (offset + 0x4), (const u_int16_t
*)(((u_int8_t *)((m)->m_hdr.mh_data))), (m->m_hdr.mh_len
& ~1) >> 1))
;
1094 if (m->m_lenm_hdr.mh_len & 1)
1095 bus_space_write_1(bst, bsh, offset + EDP,((bst)->write_1((bsh), (offset + 0x4), (*(((u_int8_t *)((m
)->m_hdr.mh_data)) + m->m_hdr.mh_len - 1))))
1096 *(mtod(m, u_int8_t *) + m->m_len - 1))((bst)->write_1((bsh), (offset + 0x4), (*(((u_int8_t *)((m
)->m_hdr.mh_data)) + m->m_hdr.mh_len - 1))))
;
1097 m0 = m_free(m);
1098 m = m0;
1099 }
1100 if (sc->sc_flags & XEF_MOHAWK0x001)
1101 bus_space_write_1(bst, bsh, offset + CR, TX_PKT | ENABLE_INT)((bst)->write_1((bsh), (offset + 0x0), (0x01 | 0x04)));
1102 else {
1103 for (; pad > 1; pad -= 2)
1104 bus_space_write_2(bst, bsh, offset + EDP, 0)((bst)->write_2((bsh), (offset + 0x4), (0)));
1105 if (pad == 1)
1106 bus_space_write_1(bst, bsh, offset + EDP, 0)((bst)->write_1((bsh), (offset + 0x4), (0)));
1107 }
1108
1109 splx(s)spllower(s);
1110
1111 ifp->if_timer = 5;
1112}
1113
1114int
1115xe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1116{
1117 struct xe_softc *sc = ifp->if_softc;
1118 struct ifreq *ifr = (struct ifreq *)data;
1119 int s, error = 0;
1120
1121 s = splnet()splraise(0x7);
1122
1123 switch (command) {
1124 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1125 ifp->if_flags |= IFF_UP0x1;
1126 xe_init(sc);
1127 break;
1128
1129 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1130 sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI0x200) ? 1 : 0;
1131
1132 PAGE(sc, 0x42)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x42))))
;
1133 if ((ifp->if_flags & IFF_PROMISC0x100) ||
1134 (ifp->if_flags & IFF_ALLMULTI0x200))
1135 bus_space_write_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
1136 sc->sc_offset + SWC1,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
1137 SWC1_PROMISC | SWC1_MCAST_PROM)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
;
1138 else
1139 bus_space_write_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0)))
1140 sc->sc_offset + SWC1, 0)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0)))
;
1141
1142 /*
1143 * If interface is marked up and not running, then start it.
1144 * If it is marked down and running, stop it.
1145 * XXX If it's up then re-initialize it. This is so flags
1146 * such as IFF_PROMISC are handled.
1147 */
1148 if (ifp->if_flags & IFF_UP0x1) {
1149 xe_init(sc);
1150 } else {
1151 if (ifp->if_flags & IFF_RUNNING0x40)
1152 xe_stop(sc);
1153 }
1154 break;
1155
1156 case SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
:
1157 case SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
:
1158 sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI0x200) ? 1 : 0;
1159 error = (command == SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
) ?
1160 ether_addmulti(ifr, &sc->sc_arpcom) :
1161 ether_delmulti(ifr, &sc->sc_arpcom);
1162
1163 if (error == ENETRESET52) {
1164 /*
1165 * Multicast list has changed; set the hardware
1166 * filter accordingly.
1167 */
1168 if (!sc->sc_all_mcasts &&
1169 !(ifp->if_flags & IFF_PROMISC0x100))
1170 xe_set_address(sc);
1171
1172 /*
1173 * xe_set_address() can turn on all_mcasts if we run
1174 * out of space, so check it again rather than else {}.
1175 */
1176 if (sc->sc_all_mcasts)
1177 xe_init(sc);
1178 error = 0;
1179 }
1180 break;
1181
1182 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
1183 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
1184 error =
1185 ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
1186 break;
1187
1188 default:
1189 error = ENOTTY25;
1190 }
1191
1192 splx(s)spllower(s);
1193 return (error);
1194}
1195
1196void
1197xe_set_address(struct xe_softc *sc)
1198{
1199 bus_space_tag_t bst = sc->sc_bst;
1200 bus_space_handle_t bsh = sc->sc_bsh;
1201 bus_size_t offset = sc->sc_offset;
1202 struct arpcom *arp = &sc->sc_arpcom;
1203 struct ether_multi *enm;
1204 struct ether_multistep step;
1205 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1206 int i, page, pos, num;
1207
1208 PAGE(sc, 0x50)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x50))))
;
1209 for (i = 0; i < 6; i++) {
1210 bus_space_write_1(bst, bsh, offset + IA + i,((bst)->write_1((bsh), (offset + 0x8 + i), (sc->sc_arpcom
.ac_enaddr[(sc->sc_flags & 0x001) ? 5 - i : i])))
1211 sc->sc_arpcom.ac_enaddr[(sc->sc_flags & XEF_MOHAWK) ?((bst)->write_1((bsh), (offset + 0x8 + i), (sc->sc_arpcom
.ac_enaddr[(sc->sc_flags & 0x001) ? 5 - i : i])))
1212 5 - i : i])((bst)->write_1((bsh), (offset + 0x8 + i), (sc->sc_arpcom
.ac_enaddr[(sc->sc_flags & 0x001) ? 5 - i : i])))
;
1213 }
1214
1215 if (arp->ac_multirangecnt > 0) {
1216 ifp->if_flags |= IFF_ALLMULTI0x200;
1217 sc->sc_all_mcasts=1;
1218 } else if (arp->ac_multicnt > 0) {
1219 if (arp->ac_multicnt > 9) {
1220 PAGE(sc, 0x42)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x42))))
;
1221 bus_space_write_1(sc->sc_bst, sc->sc_bsh,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
1222 sc->sc_offset + SWC1,((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
1223 SWC1_PROMISC | SWC1_MCAST_PROM)((sc->sc_bst)->write_1((sc->sc_bsh), (sc->sc_offset
+ 0x9), (0x04 | 0x02)))
;
1224 return;
1225 }
1226
1227 ETHER_FIRST_MULTI(step, arp, enm)do { (step).e_enm = ((&(arp)->ac_multiaddrs)->lh_first
); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step
)).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while
( 0)
;
1228
1229 pos = IA0x8 + 6;
1230 for (page = 0x50, num = arp->ac_multicnt; num > 0 && enm;
1231 num--) {
1232 for (i = 0; i < 6; i++) {
1233 bus_space_write_1(bst, bsh, offset + pos,((bst)->write_1((bsh), (offset + pos), (enm->enm_addrlo
[ (sc->sc_flags & 0x001) ? 5 - i : i])))
1234 enm->enm_addrlo[((bst)->write_1((bsh), (offset + pos), (enm->enm_addrlo
[ (sc->sc_flags & 0x001) ? 5 - i : i])))
1235 (sc->sc_flags & XEF_MOHAWK) ? 5 - i : i])((bst)->write_1((bsh), (offset + pos), (enm->enm_addrlo
[ (sc->sc_flags & 0x001) ? 5 - i : i])))
;
1236
1237 if (++pos > 15) {
1238 pos = IA0x8;
1239 page++;
1240 PAGE(sc, page)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((page))))
;
1241 }
1242 }
1243 }
1244 }
1245}
1246
1247void
1248xe_cycle_power(struct xe_softc *sc)
1249{
1250 bus_space_tag_t bst = sc->sc_bst;
1251 bus_space_handle_t bsh = sc->sc_bsh;
1252 bus_size_t offset = sc->sc_offset;
1253
1254 PAGE(sc, 4)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((4))))
;
1255 DELAY(1)(*delay_func)(1);
1256 bus_space_write_1(bst, bsh, offset + GP1, 0)((bst)->write_1((bsh), (offset + 0x9), (0)));
1257 DELAY(40000)(*delay_func)(40000);
1258 if (sc->sc_flags & XEF_MOHAWK0x001)
1259 bus_space_write_1(bst, bsh, offset + GP1, POWER_UP)((bst)->write_1((bsh), (offset + 0x9), (0x01)));
1260 else
1261 /* XXX What is bit 2 (aka AIC)? */
1262 bus_space_write_1(bst, bsh, offset + GP1, POWER_UP | 4)((bst)->write_1((bsh), (offset + 0x9), (0x01 | 4)));
1263 DELAY(20000)(*delay_func)(20000);
1264}
1265
1266void
1267xe_full_reset(struct xe_softc *sc)
1268{
1269 bus_space_tag_t bst = sc->sc_bst;
1270 bus_space_handle_t bsh = sc->sc_bsh;
1271 bus_size_t offset = sc->sc_offset;
1272
1273 /* Do an as extensive reset as possible on all functions. */
1274 xe_cycle_power(sc);
1275 bus_space_write_1(bst, bsh, offset + CR, SOFT_RESET)((bst)->write_1((bsh), (offset + 0x0), (0x02)));
1276 DELAY(20000)(*delay_func)(20000);
1277 bus_space_write_1(bst, bsh, offset + CR, 0)((bst)->write_1((bsh), (offset + 0x0), (0)));
1278 DELAY(20000)(*delay_func)(20000);
1279 if (sc->sc_flags & XEF_MOHAWK0x001) {
1280 PAGE(sc, 4)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((4))))
;
1281 /*
1282 * Drive GP1 low to power up ML6692 and GP2 high to power up
1283 * the 10MHz chip. XXX What chip is that? The phy?
1284 */
1285 bus_space_write_1(bst, bsh, offset + GP0,((bst)->write_1((bsh), (offset + 0x8), (0x04 | 0x08 | 0x02
)))
1286 GP1_OUT | GP2_OUT | GP2_WR)((bst)->write_1((bsh), (offset + 0x8), (0x04 | 0x08 | 0x02
)))
;
1287 }
1288 DELAY(500000)(*delay_func)(500000);
1289
1290 /* Get revision information. XXX Symbolic constants. */
1291 sc->sc_rev = bus_space_read_1(bst, bsh, offset + BV)((bst)->read_1((bsh), (offset + 0xa))) &
1292 ((sc->sc_flags & XEF_MOHAWK0x001) ? 0x70 : 0x30) >> 4;
1293
1294 /* Media selection. XXX Maybe manual overriding too? */
1295 if (!(sc->sc_flags & XEF_MOHAWK0x001)) {
1296 PAGE(sc, 4)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((4))))
;
1297 /*
1298 * XXX I have no idea what this really does, it is from the
1299 * Linux driver.
1300 */
1301 bus_space_write_1(bst, bsh, offset + GP0, GP1_OUT)((bst)->write_1((bsh), (offset + 0x8), (0x04)));
1302 }
1303 DELAY(40000)(*delay_func)(40000);
1304
1305 /* Setup the ethernet interrupt mask. */
1306 PAGE(sc, 1)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((1))))
;
1307 bus_space_write_1(bst, bsh, offset + IMR0,((bst)->write_1((bsh), (offset + 0xc), (0x01 | 0x02 | 0x04
| 0x20 | 0x40 | 0x80)))
1308 ISR_TX_OFLOW | ISR_PKT_TX | ISR_MAC_INT | /* ISR_RX_EARLY | */((bst)->write_1((bsh), (offset + 0xc), (0x01 | 0x02 | 0x04
| 0x20 | 0x40 | 0x80)))
1309 ISR_RX_FULL | ISR_RX_PKT_REJ | ISR_FORCED_INT)((bst)->write_1((bsh), (offset + 0xc), (0x01 | 0x02 | 0x04
| 0x20 | 0x40 | 0x80)))
;
1310#if 0
1311 bus_space_write_1(bst, bsh, offset + IMR0, 0xff)((bst)->write_1((bsh), (offset + 0xc), (0xff)));
1312#endif
1313 if (!(sc->sc_flags & XEF_DINGO0x002))
1314 /* XXX What is this? Not for Dingo at least. */
1315 bus_space_write_1(bst, bsh, offset + IMR1, 1)((bst)->write_1((bsh), (offset + 0xd), (1)));
1316
1317 /*
1318 * Disable source insertion.
1319 * XXX Dingo does not have this bit, but Linux does it unconditionally.
1320 */
1321 if (!(sc->sc_flags & XEF_DINGO0x002)) {
1322 PAGE(sc, 0x42)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x42))))
;
1323 bus_space_write_1(bst, bsh, offset + SWC0, 0x20)((bst)->write_1((bsh), (offset + 0x8), (0x20)));
1324 }
1325
1326 /* Set the local memory dividing line. */
1327 if (sc->sc_rev != 1) {
1328 PAGE(sc, 2)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((2))))
;
1329 /* XXX Symbolic constant preferrable. */
1330 bus_space_write_2(bst, bsh, offset + RBS0, 0x2000)((bst)->write_2((bsh), (offset + 0x8), (0x2000)));
1331 }
1332
1333 xe_set_address(sc);
1334
1335 /*
1336 * Apparently the receive byte pointer can be bad after a reset, so
1337 * we hardwire it correctly.
1338 */
1339 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
1340 bus_space_write_2(bst, bsh, offset + DO0, DO_CHG_OFFSET)((bst)->write_2((bsh), (offset + 0xc), (0x2000)));
1341
1342 /* Setup ethernet MAC registers. XXX Symbolic constants. */
1343 PAGE(sc, 0x40)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x40))))
;
1344 bus_space_write_1(bst, bsh, offset + RX0MSK,((bst)->write_1((bsh), (offset + 0xd), (0x02 | 0x08 | 0x10
| 0x40 | 0x80)))
1345 PKT_TOO_LONG | CRC_ERR | RX_OVERRUN | RX_ABORT | RX_OK)((bst)->write_1((bsh), (offset + 0xd), (0x02 | 0x08 | 0x10
| 0x40 | 0x80)))
;
1346 bus_space_write_1(bst, bsh, offset + TX0MSK,((bst)->write_1((bsh), (offset + 0xe), (0x01 | 0x02 | 0x08
| 0x10 | 0x20 | 0x40 | 0x80)))
1347 CARRIER_LOST | EXCESSIVE_COLL | TX_UNDERRUN | LATE_COLLISION |((bst)->write_1((bsh), (offset + 0xe), (0x01 | 0x02 | 0x08
| 0x10 | 0x20 | 0x40 | 0x80)))
1348 SQE | TX_ABORT | TX_OK)((bst)->write_1((bsh), (offset + 0xe), (0x01 | 0x02 | 0x08
| 0x10 | 0x20 | 0x40 | 0x80)))
;
1349 if (!(sc->sc_flags & XEF_DINGO0x002))
1350 /* XXX From Linux, dunno what 0xb0 means. */
1351 bus_space_write_1(bst, bsh, offset + TX1MSK, 0xb0)((bst)->write_1((bsh), (offset + 0xf), (0xb0)));
1352 bus_space_write_1(bst, bsh, offset + RXST0, 0)((bst)->write_1((bsh), (offset + 0x9), (0)));
1353 bus_space_write_1(bst, bsh, offset + TXST0, 0)((bst)->write_1((bsh), (offset + 0xb), (0)));
1354 bus_space_write_1(bst, bsh, offset + TXST1, 0)((bst)->write_1((bsh), (offset + 0xc), (0)));
1355
1356 /* Enable MII function if available. */
1357 if (LIST_FIRST(&sc->sc_mii.mii_phys)((&sc->sc_mii.mii_phys)->lh_first)) {
1358 PAGE(sc, 2)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((2))))
;
1359 bus_space_write_1(bst, bsh, offset + MSR,((bst)->write_1((bsh), (offset + 0xc), (((bst)->read_1(
(bsh), (offset + 0xc))) | 0x08)))
1360 bus_space_read_1(bst, bsh, offset + MSR) | SELECT_MII)((bst)->write_1((bsh), (offset + 0xc), (((bst)->read_1(
(bsh), (offset + 0xc))) | 0x08)))
;
1361 DELAY(20000)(*delay_func)(20000);
1362 } else {
1363 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
1364
1365 /* XXX Do we need to do this? */
1366 PAGE(sc, 0x42)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x42))))
;
1367 bus_space_write_1(bst, bsh, offset + SWC1, SWC1_AUTO_MEDIA)((bst)->write_1((bsh), (offset + 0x9), (0x80)));
1368 DELAY(50000)(*delay_func)(50000);
1369
1370 /* XXX Linux probes the media here. */
1371 }
1372
1373 /* Configure the LED registers. */
1374 PAGE(sc, 2)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((2))))
;
1375
1376 /* XXX This is not good for 10base2. */
1377 bus_space_write_1(bst, bsh, offset + LED,((bst)->write_1((bsh), (offset + 0xa), (7 << 3 | 3 <<
0)))
1378 LED_TX_ACT << LED1_SHIFT | LED_10MB_LINK << LED0_SHIFT)((bst)->write_1((bsh), (offset + 0xa), (7 << 3 | 3 <<
0)))
;
1379 if (sc->sc_flags & XEF_DINGO0x002)
1380 bus_space_write_1(bst, bsh, offset + LED3,((bst)->write_1((bsh), (offset + 0xb), (4 << 0)))
1381 LED_100MB_LINK << LED3_SHIFT)((bst)->write_1((bsh), (offset + 0xb), (4 << 0)));
1382
1383 /* Enable receiver and go online. */
1384 PAGE(sc, 0x40)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0x40))))
;
1385 bus_space_write_1(bst, bsh, offset + CMD0, ENABLE_RX | ONLINE)((bst)->write_1((bsh), (offset + 0x8), (0x20 | 0x04)));
1386
1387#if 0
1388 /* XXX Linux does this here - is it necessary? */
1389 PAGE(sc, 1)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((1))))
;
1390 bus_space_write_1(bst, bsh, offset + IMR0, 0xff)((bst)->write_1((bsh), (offset + 0xc), (0xff)));
1391 if (!(sc->sc_flags & XEF_DINGO0x002))
1392 /* XXX What is this? Not for Dingo at least. */
1393 bus_space_write_1(bst, bsh, offset + IMR1, 1)((bst)->write_1((bsh), (offset + 0xd), (1)));
1394#endif
1395
1396 /* Enable interrupts. */
1397 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
1398 bus_space_write_1(bst, bsh, offset + CR, ENABLE_INT)((bst)->write_1((bsh), (offset + 0x0), (0x04)));
1399
1400 /* XXX This is pure magic for me, found in the Linux driver. */
1401 if ((sc->sc_flags & (XEF_DINGO0x002 | XEF_MODEM0x004)) == XEF_MODEM0x004) {
1402 if ((bus_space_read_1(bst, bsh, offset + 0x10)((bst)->read_1((bsh), (offset + 0x10))) & 0x01) == 0)
1403 /* Unmask the master interrupt bit. */
1404 bus_space_write_1(bst, bsh, offset + 0x10, 0x11)((bst)->write_1((bsh), (offset + 0x10), (0x11)));
1405 }
1406
1407 /*
1408 * The Linux driver says this:
1409 * We should switch back to page 0 to avoid a bug in revision 0
1410 * where regs with offset below 8 can't be read after an access
1411 * to the MAC registers.
1412 */
1413 PAGE(sc, 0)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((0))))
;
1414}
1415
1416#ifdef XEDEBUG
1417void
1418xe_reg_dump(struct xe_softc *sc)
1419{
1420 int page, i;
1421 bus_space_tag_t bst = sc->sc_bst;
1422 bus_space_handle_t bsh = sc->sc_bsh;
1423 bus_size_t offset = sc->sc_offset;
1424
1425 printf("%x: Common registers: ", sc->sc_dev.dv_xname);
1426 for (i = 0; i < 8; i++) {
1427 printf(" %2.2x", bus_space_read_1(bst, bsh, offset + i)((bst)->read_1((bsh), (offset + i))));
1428 }
1429 printf("\n");
1430
1431 for (page = 0; page < 8; page++) {
1432 printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
1433 PAGE(sc, page)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((page))))
;
1434 for (i = 8; i < 16; i++) {
1435 printf(" %2.2x",
1436 bus_space_read_1(bst, bsh, offset + i)((bst)->read_1((bsh), (offset + i))));
1437 }
1438 printf("\n");
1439 }
1440
1441 for (page = 0x40; page < 0x5f; page++) {
1442 if (page == 0x43 || (page >= 0x46 && page <= 0x4f) ||
1443 (page >= 0x51 && page <= 0x5e))
1444 continue;
1445 printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
1446 PAGE(sc, page)(((sc->sc_bst))->write_1(((sc->sc_bsh)), ((sc->sc_offset
) + 0x1), ((page))))
;
1447 for (i = 8; i < 16; i++) {
1448 printf(" %2.2x",
1449 bus_space_read_1(bst, bsh, offset + i)((bst)->read_1((bsh), (offset + i))));
1450 }
1451 printf("\n");
1452 }
1453}
1454#endif /* XEDEBUG */