1/*
2 * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core.
3 *
4 * This file implements the chip-specific routines
5 * for Broadcom HNBU Sonics SiliconBackplane enet cores.
6 *
7 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
16 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * $Id: etc47xx.c 423696 2013-09-13 00:56:28Z $
21 */
22
23#include <et_cfg.h>
24#include <typedefs.h>
25#include <osl.h>
26#include <bcmdefs.h>
27#include <bcmendian.h>
28#include <bcmutils.h>
29#include <bcmdevs.h>
30#include <proto/ethernet.h>
31#include <siutils.h>
32#include <sbhnddma.h>
33#include <hnddma.h>
34#include <et_dbg.h>
35#include <hndsoc.h>
36#include <bcmenet47xx.h>
37#include <et_export.h>		/* for et_phyxx() routines */
38
39#ifdef ETROBO
40#include <bcmrobo.h>
41#endif /* ETROBO */
42#ifdef ETADM
43#include <etc_adm.h>
44#endif /* ETADM */
45
46struct bcm4xxx;	/* forward declaration */
47#define ch_t	struct bcm4xxx
48#include <etc.h>
49
50/* private chip state */
51struct bcm4xxx {
52	void 		*et;		/* pointer to et private state */
53	etc_info_t	*etc;		/* pointer to etc public state */
54
55	bcmenetregs_t	*regs;		/* pointer to chip registers */
56	osl_t 		*osh;		/* os handle */
57
58	void 		*etphy;		/* pointer to et for shared mdc/mdio contortion */
59
60	uint32		intstatus;	/* saved interrupt condition bits */
61	uint32		intmask;	/* current software interrupt mask */
62
63	hnddma_t	*di;		/* dma engine software state */
64
65	bool		mibgood;	/* true once mib registers have been cleared */
66	bcmenetmib_t	mib;		/* mib counters */
67	si_t 		*sih;		/* si utils handle */
68
69	char		*vars;		/* sprom name=value */
70	uint		vars_size;
71
72	void		*adm;		/* optional admtek private data */
73};
74
75/* local prototypes */
76static bool chipid(uint vendor, uint device);
77static void *chipattach(etc_info_t *etc, void *osh, void *regsva);
78static void chipdetach(ch_t *ch);
79static void chipreset(ch_t *ch);
80static void chipinit(ch_t *ch, uint options);
81static bool chiptx(ch_t *ch, void *p);
82static void *chiprx(ch_t *ch);
83static void chiprxfill(ch_t *ch);
84static int chipgetintrevents(ch_t *ch, bool in_isr);
85static bool chiperrors(ch_t *ch);
86static void chipintrson(ch_t *ch);
87static void chipintrsoff(ch_t *ch);
88static void chiptxreclaim(ch_t *ch, bool all);
89static void chiprxreclaim(ch_t *ch);
90static void chipstatsupd(ch_t *ch);
91static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear);
92static void chipenablepme(ch_t *ch);
93static void chipdisablepme(ch_t *ch);
94static void chipphyreset(ch_t *ch, uint phyaddr);
95static void chipphyinit(ch_t *ch, uint phyaddr);
96static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg);
97static void chipdump(ch_t *ch, struct bcmstrbuf *b);
98static void chiplongname(ch_t *ch, char *buf, uint bufsize);
99static void chipduplexupd(ch_t *ch);
100static void chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex);
101static void chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
102static void chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
103static void chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
104static void chipphyforce(struct bcm4xxx *ch, uint phyaddr);
105static void chipphyadvertise(struct bcm4xxx *ch, uint phyaddr);
106#ifdef BCMDBG
107static void chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, struct bcmstrbuf *b);
108#endif /* BCMDBG */
109
110/* chip interrupt bit error summary */
111#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
112#define	DEF_INTMASK	(I_XI | I_RI | I_ERRORS)
113
114struct chops bcm47xx_et_chops = {
115	chipid,
116	chipattach,
117	chipdetach,
118	chipreset,
119	chipinit,
120	chiptx,
121	chiprx,
122	chiprxfill,
123	chipgetintrevents,
124	chiperrors,
125	NULL,
126	chipintrson,
127	chipintrsoff,
128	chiptxreclaim,
129	chiprxreclaim,
130	chipstatsupd,
131	chipdumpmib,
132	chipenablepme,
133	chipdisablepme,
134	chipphyreset,
135	chipphyrd,
136	chipphywr,
137	chipdump,
138	chiplongname,
139	chipduplexupd
140};
141
142static uint devices[] = {
143	BCM47XX_ENET_ID,
144	0x0000 };
145
146static bool
147chipid(uint vendor, uint device)
148{
149	int i;
150
151	if (vendor != VENDOR_BROADCOM)
152		return (FALSE);
153
154	for (i = 0; devices[i]; i++) {
155		if (device == devices[i])
156			return (TRUE);
157	}
158	return (FALSE);
159}
160
161static void *
162chipattach(etc_info_t *etc, void *osh, void *regsva)
163{
164	struct bcm4xxx *ch;
165	bcmenetregs_t *regs;
166	char name[16];
167	char *var;
168	uint boardflags, boardtype;
169
170	ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva));
171
172	if ((ch = (struct bcm4xxx *)MALLOC(osh, sizeof(struct bcm4xxx))) == NULL) {
173		ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit,
174		          MALLOCED(osh)));
175		return (NULL);
176	}
177	bzero((char *)ch, sizeof(struct bcm4xxx));
178
179	ch->etc = etc;
180	ch->et = etc->et;
181	ch->osh = osh;
182
183	/* store the pointer to the sw mib */
184	etc->mib = (void *)&ch->mib;
185
186	/* get si handle */
187	if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars,
188	                         &ch->vars_size)) == NULL) {
189		ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit));
190		goto fail;
191	}
192
193	/* We used to have an assert here like:
194	 *	si_coreid(ch->sih) == ENET_CORE_ID
195	 * but srom-less systems and simulators don't have a way to
196	 * provide a default bar0window so we were relying on nvram
197	 * variables. At some point we decided that we could do away
198	 * with that since the wireless driver was simply doing a
199	 * setcore in attach. So we need to do the same here for
200	 * the ethernet.
201	 */
202	if ((regs = (bcmenetregs_t *)si_setcore(ch->sih, ENET_CORE_ID, etc->unit)) == NULL) {
203		ET_ERROR(("et%d: chipattach: Could not setcore to the ENET core\n", etc->unit));
204		goto fail;
205	}
206
207	ch->regs = regs;
208	etc->chip = ch->sih->chip;
209	etc->chiprev = ch->sih->chiprev;
210	etc->coreid = si_coreid(ch->sih);
211	etc->corerev = si_corerev(ch->sih);
212	etc->nicmode = !(ch->sih->bustype == SI_BUS);
213	etc->coreunit = si_coreunit(ch->sih);
214	etc->boardflags = getintvar(ch->vars, "boardflags");
215
216	boardflags = etc->boardflags;
217	boardtype = ch->sih->boardtype;
218
219	/* get our local ether addr */
220	sprintf(name, "et%dmacaddr", etc->coreunit);
221	var = getvar(ch->vars, name);
222	if (var == NULL) {
223		ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
224		goto fail;
225	}
226	bcm_ether_atoe(var, &etc->perm_etheraddr);
227
228	if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) {
229		ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var));
230		goto fail;
231	}
232	bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN);
233
234	/*
235	 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
236	 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
237	 */
238
239	/* get our phyaddr value */
240	sprintf(name, "et%dphyaddr", etc->coreunit);
241	var = getvar(ch->vars, name);
242	if (var == NULL) {
243		ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
244		goto fail;
245	}
246	etc->phyaddr = bcm_atoi(var) & EPHY_MASK;
247
248	/* nvram says no phy is present */
249	if (etc->phyaddr == EPHY_NONE) {
250		ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit));
251		goto fail;
252	}
253
254	/* get our mdc/mdio port number */
255	sprintf(name, "et%dmdcport", etc->coreunit);
256	var = getvar(ch->vars, name);
257	if (var == NULL) {
258		ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
259		goto fail;
260	}
261	etc->mdcport = bcm_atoi(var);
262
263	/* configure pci core */
264	si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
265
266	/* reset the enet core */
267	chipreset(ch);
268
269	/* dma attach */
270	sprintf(name, "et%d", etc->coreunit);
271	if ((ch->di = dma_attach(osh, name, ch->sih,
272	                         (void *)&regs->dmaregs.xmt, (void *)&regs->dmaregs.rcv,
273	                         NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF,
274	                         &et_msg_level)) == NULL) {
275		ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit));
276		goto fail;
277	}
278	etc->txavail[TX_Q0] = (uint *)&ch->di->txavail;
279
280	/* set default sofware intmask */
281	ch->intmask = DEF_INTMASK;
282
283	/*
284	 * For the 5222 dual phy shared mdio contortion, our phy is
285	 * on someone elses mdio pins.  This other enet enet
286	 * may not yet be attached so we must defer the et_phyfind().
287	 */
288	/* if local phy: reset it once now */
289	if (etc->mdcport == etc->coreunit)
290		chipphyreset(ch, etc->phyaddr);
291
292#ifdef ETROBO
293	/*
294	 * Broadcom Robo ethernet switch.
295	 */
296	if ((boardflags & BFL_ENETROBO) &&
297	    (etc->phyaddr == EPHY_NOREG)) {
298		/* Attach to the switch */
299		if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars,
300		                                  (miird_f)bcm47xx_et_chops.phyrd,
301		                                  (miiwr_f)bcm47xx_et_chops.phywr))) {
302			ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit));
303			goto fail;
304		}
305		/* Enable the switch and set it to a known good state */
306		if (bcm_robo_enable_device(etc->robo)) {
307			ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit));
308			goto fail;
309		}
310		/* Configure the switch to do VLAN */
311		if ((boardflags & BFL_ENETVLAN) &&
312		    bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) {
313			ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit));
314			goto fail;
315		}
316		/* Enable switching/forwarding */
317		if (bcm_robo_enable_switch(etc->robo)) {
318			ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit));
319			goto fail;
320		}
321	}
322#endif /* ETROBO */
323
324#ifdef ETADM
325	/*
326	 * ADMtek ethernet switch.
327	 */
328	if (boardflags & BFL_ENETADM) {
329		/* Attach to the device */
330		if (!(ch->adm = adm_attach(ch->sih, ch->vars))) {
331			ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc->unit));
332			goto fail;
333		}
334		/* Enable the external switch and set it to a known good state */
335		if (adm_enable_device(ch->adm)) {
336			ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc->unit));
337			goto fail;
338		}
339		/* Configure the switch */
340		if ((boardflags & BFL_ENETVLAN) && adm_config_vlan(ch->adm)) {
341			ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc->unit));
342			goto fail;
343		}
344	}
345#endif /* ETADM */
346
347	return ((void *)ch);
348
349fail:
350	chipdetach(ch);
351	return (NULL);
352}
353
354static void
355chipdetach(struct bcm4xxx *ch)
356{
357	ET_TRACE(("et%d: chipdetach\n", ch->etc->unit));
358
359	if (ch == NULL)
360		return;
361
362#ifdef ETROBO
363	/* free robo state */
364	if (ch->etc->robo)
365		bcm_robo_detach(ch->etc->robo);
366#endif /* ETROBO */
367
368#ifdef ETADM
369	/* free ADMtek state */
370	if (ch->adm)
371		adm_detach(ch->adm);
372#endif /* ETADM */
373
374	/* free dma state */
375	if (ch->di)
376		dma_detach(ch->di);
377	ch->di = NULL;
378
379	/* put the core back into reset */
380	if (ch->sih)
381		si_core_disable(ch->sih, 0);
382
383	/* free si handle */
384	si_detach(ch->sih);
385	ch->sih = NULL;
386
387	/* free vars */
388	if (ch->vars)
389		MFREE(ch->osh, ch->vars, ch->vars_size);
390
391	/* free chip private state */
392	MFREE(ch->osh, ch, sizeof(struct bcm4xxx));
393}
394
395static void
396chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize)
397{
398	char *s;
399
400	switch (ch->etc->deviceid) {
401	case BCM47XX_ENET_ID:
402	default:
403		s = "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
404		break;
405	}
406
407	strncpy(buf, s, bufsize);
408	buf[bufsize - 1] = '\0';
409}
410
411static void
412chipdump(struct bcm4xxx *ch, struct bcmstrbuf *b)
413{
414#ifdef BCMDBG
415	bcm_bprintf(b, "regs 0x%x etphy 0x%x ch->intstatus 0x%x intmask 0x%x\n",
416		(ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask);
417	bcm_bprintf(b, "\n");
418
419	/* dma engine state */
420	dma_dump(ch->di, b, FALSE);
421	bcm_bprintf(b, "\n");
422
423	/* registers */
424	chipdumpregs(ch, ch->regs, b);
425	bcm_bprintf(b, "\n");
426
427	/* switch registers */
428#ifdef ETROBO
429	if (ch->etc->robo)
430		robo_dump_regs(ch->etc->robo, b);
431#endif /* ETROBO */
432#ifdef ETADM
433	if (ch->adm)
434		adm_dump_regs(ch->adm, b->buf);
435#endif /* ETADM */
436#endif	/* BCMDBG */
437}
438
439#ifdef BCMDBG
440
441#define	PRREG(name)	bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->name))
442#define	PRMIBREG(name)	bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->mib.name))
443
444static void
445chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, struct bcmstrbuf *b)
446{
447	uint phyaddr;
448
449	phyaddr = ch->etc->phyaddr;
450
451	PRREG(devcontrol); PRREG(biststatus); PRREG(wakeuplength);
452	bcm_bprintf(b, "\n");
453	PRREG(intstatus); PRREG(intmask); PRREG(gptimer);
454	bcm_bprintf(b, "\n");
455	PRREG(emactxmaxburstlen); PRREG(emacrxmaxburstlen);
456	PRREG(emaccontrol); PRREG(emacflowcontrol);
457	bcm_bprintf(b, "\n");
458	PRREG(intrecvlazy);
459	bcm_bprintf(b, "\n");
460
461	/* emac registers */
462	PRREG(rxconfig); PRREG(rxmaxlength); PRREG(txmaxlength);
463	bcm_bprintf(b, "\n");
464	PRREG(mdiocontrol); PRREG(camcontrol); PRREG(enetcontrol);
465	bcm_bprintf(b, "\n");
466	PRREG(txcontrol); PRREG(txwatermark); PRREG(mibcontrol);
467	bcm_bprintf(b, "\n");
468
469	/* mib registers */
470	PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts);
471	bcm_bprintf(b, "\n");
472	PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts);
473	bcm_bprintf(b, "\n");
474	PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts);
475	bcm_bprintf(b, "\n");
476	PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols);
477	bcm_bprintf(b, "\n");
478	PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols);
479	bcm_bprintf(b, "\n");
480	PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts);
481	bcm_bprintf(b, "\n");
482
483	PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts);
484	bcm_bprintf(b, "\n");
485	PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts);
486	bcm_bprintf(b, "\n");
487	PRMIBREG(rx_jabber_pkts); PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts);
488	bcm_bprintf(b, "\n");
489	PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize);
490	bcm_bprintf(b, "\n");
491	PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs);
492	bcm_bprintf(b, "\n");
493	PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts);
494	bcm_bprintf(b, "\n");
495
496	if (phyaddr != EPHY_NOREG) {
497		/* print a few interesting phy registers */
498		bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n",
499		               chipphyrd(ch, phyaddr, 0),
500		               chipphyrd(ch, phyaddr, 1),
501		               chipphyrd(ch, phyaddr, 2),
502		               chipphyrd(ch, phyaddr, 3));
503		bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n",
504		               chipphyrd(ch, phyaddr, 4),
505		               chipphyrd(ch, phyaddr, 5),
506		               chipphyrd(ch, phyaddr, 24),
507		               chipphyrd(ch, phyaddr, 25));
508	}
509
510}
511#endif	/* BCMDBG */
512
513#define	MDC_RATIO	5000000
514
515static void
516chipreset(struct bcm4xxx *ch)
517{
518	bcmenetregs_t *regs;
519	uint32 clk, mdc;
520
521	ET_TRACE(("et%d: chipreset\n", ch->etc->unit));
522
523	regs = ch->regs;
524
525	if (!si_iscoreup(ch->sih)) {
526		if (!ch->etc->nicmode)
527			si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
528		/* power on reset: reset the enet core */
529		si_core_reset(ch->sih, 0, 0);
530		goto chipinreset;
531	}
532
533	/* read counters before resetting the chip */
534	if (ch->mibgood)
535		chipstatsupd(ch);
536
537	/* reset the tx dma engine */
538	if (ch->di)
539		dma_txreset(ch->di);
540
541	/* set emac into loopback mode to ensure no rx traffic */
542	W_REG(ch->osh, &regs->rxconfig, ERC_LE);
543	OSL_DELAY(1);
544
545	/* reset the rx dma engine */
546	if (ch->di)
547		dma_rxreset(ch->di);
548
549	/* reset core */
550	si_core_reset(ch->sih, 0, 0);
551
552chipinreset:
553
554	/* must clear mib registers by hand */
555	W_REG(ch->osh, &regs->mibcontrol, EMC_RZ);
556	(void) R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
557	(void) R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
558	(void) R_REG(ch->osh, &regs->mib.tx_len_64);
559	(void) R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
560	(void) R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
561	(void) R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
562	(void) R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
563	(void) R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
564	(void) R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
565	(void) R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
566	(void) R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
567	(void) R_REG(ch->osh, &regs->mib.tx_underruns);
568	(void) R_REG(ch->osh, &regs->mib.tx_total_cols);
569	(void) R_REG(ch->osh, &regs->mib.tx_single_cols);
570	(void) R_REG(ch->osh, &regs->mib.tx_multiple_cols);
571	(void) R_REG(ch->osh, &regs->mib.tx_excessive_cols);
572	(void) R_REG(ch->osh, &regs->mib.tx_late_cols);
573	(void) R_REG(ch->osh, &regs->mib.tx_defered);
574	(void) R_REG(ch->osh, &regs->mib.tx_carrier_lost);
575	(void) R_REG(ch->osh, &regs->mib.tx_pause_pkts);
576	(void) R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
577	(void) R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
578	(void) R_REG(ch->osh, &regs->mib.rx_len_64);
579	(void) R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
580	(void) R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
581	(void) R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
582	(void) R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
583	(void) R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
584	(void) R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
585	(void) R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
586	(void) R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
587	(void) R_REG(ch->osh, &regs->mib.rx_missed_pkts);
588	(void) R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
589	(void) R_REG(ch->osh, &regs->mib.rx_undersize);
590	(void) R_REG(ch->osh, &regs->mib.rx_crc_errs);
591	(void) R_REG(ch->osh, &regs->mib.rx_align_errs);
592	(void) R_REG(ch->osh, &regs->mib.rx_symbol_errs);
593	(void) R_REG(ch->osh, &regs->mib.rx_pause_pkts);
594	(void) R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
595	ch->mibgood = TRUE;
596
597	/*
598	 * We want the phy registers to be accessible even when
599	 * the driver is "downed" so initialize MDC preamble, frequency,
600	 * and whether internal or external phy here.
601	 */
602	/* default:  100Mhz SI clock and external phy */
603	W_REG(ch->osh, &regs->mdiocontrol, 0x94);
604	if (ch->etc->deviceid == BCM47XX_ENET_ID) {
605		/* 47xx chips: find out the clock */
606		if ((clk = si_clock(ch->sih)) != 0) {
607			mdc = 0x80 | ((clk + (MDC_RATIO / 2)) / MDC_RATIO);
608			W_REG(ch->osh, &regs->mdiocontrol, mdc);
609		} else {
610			ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
611			          "using 100Mhz\n",
612			          ch->etc->unit));
613		}
614	}
615
616	/* some chips have internal phy, some don't */
617	if (!(R_REG(ch->osh, &regs->devcontrol) & DC_IP)) {
618		W_REG(ch->osh, &regs->enetcontrol, EC_EP);
619	} else if (R_REG(ch->osh, &regs->devcontrol) & DC_ER) {
620		AND_REG(ch->osh, &regs->devcontrol, ~DC_ER);
621		OSL_DELAY(100);
622		chipphyinit(ch, ch->etc->phyaddr);
623	}
624
625	/* clear persistent sw intstatus */
626	ch->intstatus = 0;
627}
628
629/*
630 * Initialize all the chip registers.  If dma mode, init tx and rx dma engines
631 * but leave the devcontrol tx and rx (fifos) disabled.
632 */
633static void
634chipinit(struct bcm4xxx *ch, uint options)
635{
636	etc_info_t *etc;
637	bcmenetregs_t *regs;
638	uint idx;
639	uint i;
640
641	regs = ch->regs;
642	etc = ch->etc;
643	idx = 0;
644
645	ET_TRACE(("et%d: chipinit\n", etc->unit));
646
647	/* enable crc32 generation */
648	OR_REG(ch->osh, &regs->emaccontrol, EMC_CG);
649
650	/* enable one rx interrupt per received frame */
651	W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));
652
653	/* enable 802.3x tx flow control (honor received PAUSE frames) */
654	W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);
655
656	/* initialize CAM */
657	if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
658		OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
659	else {
660		/* our local address */
661		chipwrcam(ch, &etc->cur_etheraddr, idx++);
662
663		/* allmulti or a list of discrete multicast addresses */
664		if (etc->allmulti)
665			OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
666		else if (etc->nmulticast) {
667			for (i = 0; i < etc->nmulticast; i++)
668				chipwrcam(ch, &etc->multicast[i], idx++);
669		}
670
671		/* enable cam */
672		OR_REG(ch->osh, &regs->camcontrol, CC_CE);
673	}
674
675	/* optionally enable mac-level loopback */
676	if (etc->loopbk)
677		OR_REG(ch->osh, &regs->rxconfig, ERC_LE);
678
679	/* set max frame lengths - account for possible vlan tag */
680	W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
681	W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);
682
683	/* set tx watermark */
684	W_REG(ch->osh, &regs->txwatermark, 56);
685
686	/*
687	 * Optionally, disable phy autonegotiation and force our speed/duplex
688	 * or constrain our advertised capabilities.
689	 */
690	if (etc->forcespeed != ET_AUTO)
691		chipphyforce(ch, etc->phyaddr);
692	else if (etc->advertise && etc->needautoneg)
693		chipphyadvertise(ch, etc->phyaddr);
694
695	if (options & ET_INIT_FULL) {
696		/* initialize the tx and rx dma channels */
697		dma_txinit(ch->di);
698		dma_rxinit(ch->di);
699
700		/* post dma receive buffers */
701		dma_rxfill(ch->di);
702
703		/* lastly, enable interrupts */
704		if (options & ET_INIT_INTRON)
705			et_intrson(etc->et);
706	}
707	else
708		dma_rxenable(ch->di);
709
710	/* turn on the emac */
711	OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
712}
713
714/* dma transmit */
715static bool BCMFASTPATH
716chiptx(struct bcm4xxx *ch, void *p0)
717{
718	int error;
719
720	ET_TRACE(("et%d: chiptx\n", ch->etc->unit));
721	ET_LOG("et%d: chiptx", ch->etc->unit, 0);
722
723	error = dma_txfast(ch->di, p0, TRUE);
724
725	if (error) {
726		ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit));
727		ch->etc->txnobuf++;
728		return FALSE;
729	}
730	return TRUE;
731}
732
733/* reclaim completed transmit descriptors and packets */
734static void BCMFASTPATH
735chiptxreclaim(struct bcm4xxx *ch, bool forceall)
736{
737	ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit));
738	dma_txreclaim(ch->di, forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED);
739	ch->intstatus &= ~I_XI;
740}
741
742/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
743static void * BCMFASTPATH
744chiprx(struct bcm4xxx *ch)
745{
746	void *p;
747
748	ET_TRACE(("et%d: chiprx\n", ch->etc->unit));
749	ET_LOG("et%d: chiprx", ch->etc->unit, 0);
750
751	if ((p = dma_rx(ch->di)) == NULL)
752		ch->intstatus &= ~I_RI;
753
754	return (p);
755}
756
757/* reclaim completed dma receive descriptors and packets */
758static void
759chiprxreclaim(struct bcm4xxx *ch)
760{
761	ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit));
762	dma_rxreclaim(ch->di);
763	ch->intstatus &= ~I_RI;
764}
765
766/* allocate and post dma receive buffers */
767static void BCMFASTPATH
768chiprxfill(struct bcm4xxx *ch)
769{
770	ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit));
771	ET_LOG("et%d: chiprx", ch->etc->unit, 0);
772	dma_rxfill(ch->di);
773}
774
775/* get current and pending interrupt events */
776static int BCMFASTPATH
777chipgetintrevents(struct bcm4xxx *ch, bool in_isr)
778{
779	bcmenetregs_t *regs;
780	uint32 intstatus;
781	int events;
782
783	regs = ch->regs;
784	events = 0;
785
786	/* read the interrupt status register */
787	intstatus = R_REG(ch->osh, &regs->intstatus);
788
789	/* defer unsolicited interrupts */
790	intstatus &= (in_isr ? ch->intmask : DEF_INTMASK);
791
792	/* clear non-error interrupt conditions */
793	if (intstatus != 0) {
794		W_REG(ch->osh, &regs->intstatus, intstatus);
795		events = INTR_NEW;
796	}
797
798	/* or new bits into persistent intstatus */
799	intstatus = (ch->intstatus |= intstatus);
800
801	/* return if no events */
802	if (intstatus == 0)
803		return (0);
804
805	/* convert chip-specific intstatus bits into generic intr event bits */
806	if (intstatus & I_RI)
807		events |= INTR_RX;
808	if (intstatus & I_XI)
809		events |= INTR_TX;
810	if (intstatus & I_ERRORS)
811		events |= INTR_ERROR;
812	if (intstatus & I_TO)
813		events |= INTR_TO;
814
815	return (events);
816}
817
818/* enable chip interrupts */
819static void BCMFASTPATH
820chipintrson(struct bcm4xxx *ch)
821{
822	ch->intmask = DEF_INTMASK;
823	W_REG(ch->osh, &ch->regs->intmask, ch->intmask);
824}
825
826/* disable chip interrupts */
827static void BCMFASTPATH
828chipintrsoff(struct bcm4xxx *ch)
829{
830	W_REG(ch->osh, &ch->regs->intmask, 0);
831	(void) R_REG(ch->osh, &ch->regs->intmask);	/* sync readback */
832	ch->intmask = 0;
833}
834
835/* return true of caller should re-initialize, otherwise false */
836static bool BCMFASTPATH
837chiperrors(struct bcm4xxx *ch)
838{
839	uint32 intstatus;
840	etc_info_t *etc;
841
842	etc = ch->etc;
843
844	intstatus = ch->intstatus;
845	ch->intstatus &= ~(I_ERRORS);
846
847	ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus));
848
849	if (intstatus & I_PC) {
850		ET_ERROR(("et%d: descriptor error\n", etc->unit));
851		etc->dmade++;
852	}
853
854	if (intstatus & I_PD) {
855		ET_ERROR(("et%d: data error\n", etc->unit));
856		etc->dmada++;
857	}
858
859	if (intstatus & I_DE) {
860		ET_ERROR(("et%d: descriptor protocol error\n", etc->unit));
861		etc->dmape++;
862	}
863	/* NOTE : this ie NOT an error. It becomes an error only
864	 * when the rx fifo overflows
865	 */
866	if (intstatus & I_RU) {
867		ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit));
868		etc->rxdmauflo++;
869	}
870
871	if (intstatus & I_RO) {
872		ET_ERROR(("et%d: receive fifo overflow\n", etc->unit));
873		etc->rxoflo++;
874	}
875
876	if (intstatus & I_XU) {
877		ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit));
878		etc->txuflo++;
879	}
880	/* if overflows or decriptors underflow, don't report it
881	 * as an error and  provoque a reset
882	 */
883	if (intstatus & ~(I_RU) & I_ERRORS)
884		return (TRUE);
885	return FALSE;
886}
887
888static void
889chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
890{
891	uint32 w;
892
893	ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0);
894
895	w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8)
896		| ea->octet[5];
897	W_REG(ch->osh, &ch->regs->camdatalo, w);
898	w = CD_V | (ea->octet[0] << 8) | ea->octet[1];
899	W_REG(ch->osh, &ch->regs->camdatahi, w);
900	W_REG(ch->osh, &ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR));
901
902	/* spin until done */
903	SPINWAIT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB), 1000);
904
905	/*
906	 * This assertion is usually caused by the phy not providing a clock
907	 * to the bottom portion of the mac..
908	 */
909	ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB) == 0);
910}
911
912static void
913chipstatsupd(struct bcm4xxx *ch)
914{
915	etc_info_t *etc;
916	bcmenetregs_t *regs;
917	bcmenetmib_t *m;
918
919	etc = ch->etc;
920	regs = ch->regs;
921	m = &ch->mib;
922
923	/*
924	 * mib counters are clear-on-read.
925	 * Don't bother using the pkt and octet counters since they are only
926	 * 16bits and wrap too quickly to be useful.
927	 */
928	m->tx_broadcast_pkts += R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
929	m->tx_multicast_pkts += R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
930	m->tx_len_64 += R_REG(ch->osh, &regs->mib.tx_len_64);
931	m->tx_len_65_to_127 += R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
932	m->tx_len_128_to_255 += R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
933	m->tx_len_256_to_511 += R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
934	m->tx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
935	m->tx_len_1024_to_max += R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
936	m->tx_jabber_pkts += R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
937	m->tx_oversize_pkts += R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
938	m->tx_fragment_pkts += R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
939	m->tx_underruns += R_REG(ch->osh, &regs->mib.tx_underruns);
940	m->tx_total_cols += R_REG(ch->osh, &regs->mib.tx_total_cols);
941	m->tx_single_cols += R_REG(ch->osh, &regs->mib.tx_single_cols);
942	m->tx_multiple_cols += R_REG(ch->osh, &regs->mib.tx_multiple_cols);
943	m->tx_excessive_cols += R_REG(ch->osh, &regs->mib.tx_excessive_cols);
944	m->tx_late_cols += R_REG(ch->osh, &regs->mib.tx_late_cols);
945	m->tx_defered += R_REG(ch->osh, &regs->mib.tx_defered);
946	m->tx_carrier_lost += R_REG(ch->osh, &regs->mib.tx_carrier_lost);
947	m->tx_pause_pkts += R_REG(ch->osh, &regs->mib.tx_pause_pkts);
948	m->rx_broadcast_pkts += R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
949	m->rx_multicast_pkts += R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
950	m->rx_len_64 += R_REG(ch->osh, &regs->mib.rx_len_64);
951	m->rx_len_65_to_127 += R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
952	m->rx_len_128_to_255 += R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
953	m->rx_len_256_to_511 += R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
954	m->rx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
955	m->rx_len_1024_to_max += R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
956	m->rx_jabber_pkts += R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
957	m->rx_oversize_pkts += R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
958	m->rx_fragment_pkts += R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
959	m->rx_missed_pkts += R_REG(ch->osh, &regs->mib.rx_missed_pkts);
960	m->rx_crc_align_errs += R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
961	m->rx_undersize += R_REG(ch->osh, &regs->mib.rx_undersize);
962	m->rx_crc_errs += R_REG(ch->osh, &regs->mib.rx_crc_errs);
963	m->rx_align_errs += R_REG(ch->osh, &regs->mib.rx_align_errs);
964	m->rx_symbol_errs += R_REG(ch->osh, &regs->mib.rx_symbol_errs);
965	m->rx_pause_pkts += R_REG(ch->osh, &regs->mib.rx_pause_pkts);
966	m->rx_nonpause_pkts += R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
967
968	/*
969	 * Aggregate transmit and receive errors that probably resulted
970	 * in the loss of a frame are computed on the fly.
971	 *
972	 * We seem to get lots of tx_carrier_lost errors when flipping
973	 * speed modes so don't count these as tx errors.
974	 *
975	 * Arbitrarily lump the non-specific dma errors as tx errors.
976	 */
977	etc->rxgiants = ch->di->rxgiants;
978	etc->txerror = m->tx_jabber_pkts + m->tx_oversize_pkts
979		+ m->tx_underruns + m->tx_excessive_cols
980		+ m->tx_late_cols + etc->txnobuf + etc->dmade
981		+ etc->dmada + etc->dmape + etc->txuflo;
982	etc->rxerror = m->rx_jabber_pkts + m->rx_oversize_pkts
983		+ m->rx_missed_pkts + m->rx_crc_align_errs
984		+ m->rx_undersize + m->rx_crc_errs
985		+ m->rx_align_errs + m->rx_symbol_errs
986		+ etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen + etc->rxgiants;
987}
988
989static void
990chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear)
991{
992	bcmenetmib_t *m;
993
994	m = &ch->mib;
995
996	if (clear) {
997		bzero((char *)m, sizeof(bcmenetmib_t));
998		return;
999	}
1000
1001	bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d "
1002	               "tx_oversize_pkts %d\n",
1003	               m->tx_broadcast_pkts, m->tx_multicast_pkts,
1004	               m->tx_jabber_pkts,
1005	               m->tx_oversize_pkts);
1006	bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n",
1007	               m->tx_fragment_pkts, m->tx_underruns);
1008	bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d "
1009	               "tx_excessive_cols %d\n",
1010	               m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols,
1011	               m->tx_excessive_cols);
1012	bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n",
1013	               m->tx_late_cols, m->tx_defered, m->tx_carrier_lost,
1014	               m->tx_pause_pkts);
1015
1016	/* receive stat counters */
1017	/* hardware mib pkt and octet counters wrap too quickly to be useful */
1018	bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d "
1019	               "rx_oversize_pkts %d\n",
1020	               m->rx_broadcast_pkts, m->rx_multicast_pkts,
1021	               m->rx_jabber_pkts, m->rx_oversize_pkts);
1022	bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d "
1023	               "rx_undersize %d\n",
1024	               m->rx_fragment_pkts, m->rx_missed_pkts,
1025	               m->rx_crc_align_errs, m->rx_undersize);
1026	bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n",
1027	               m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs);
1028	bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n",
1029	               m->rx_pause_pkts, m->rx_nonpause_pkts);
1030}
1031
1032static void
1033chipenablepme(struct bcm4xxx *ch)
1034{
1035	bcmenetregs_t *regs;
1036
1037	regs = ch->regs;
1038
1039	/* enable chip wakeup pattern matching */
1040	OR_REG(ch->osh, &regs->devcontrol, DC_PM);
1041
1042	/* enable sonics bus PME */
1043	si_core_cflags(ch->sih, SICF_PME_EN, SICF_PME_EN);
1044}
1045
1046static void
1047chipdisablepme(struct bcm4xxx *ch)
1048{
1049	bcmenetregs_t *regs;
1050
1051	regs = ch->regs;
1052
1053	AND_REG(ch->osh, &regs->devcontrol, ~DC_PM);
1054	si_core_cflags(ch->sih, SICF_PME_EN, 0);
1055}
1056
1057static void
1058chipduplexupd(struct bcm4xxx *ch)
1059{
1060	uint32 txcontrol;
1061
1062	txcontrol = R_REG(ch->osh, &ch->regs->txcontrol);
1063	if (ch->etc->duplex && !(txcontrol & EXC_FD))
1064		OR_REG(ch->osh, &ch->regs->txcontrol, EXC_FD);
1065	else if (!ch->etc->duplex && (txcontrol & EXC_FD))
1066		AND_REG(ch->osh, &ch->regs->txcontrol, ~EXC_FD);
1067}
1068
1069static uint16
1070chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg)
1071{
1072	bcmenetregs_t *regs;
1073
1074	ASSERT(phyaddr < MAXEPHY);
1075
1076	/*
1077	 * BCM5222 dualphy shared mdio contortion.
1078	 * remote phy: another emac controls our phy.
1079	 */
1080	if (ch->etc->mdcport != ch->etc->coreunit) {
1081		if (ch->etphy == NULL) {
1082			ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
1083
1084			/* first time reset */
1085			if (ch->etphy)
1086				chipphyreset(ch, ch->etc->phyaddr);
1087		}
1088		if (ch->etphy)
1089			return (et_phyrd(ch->etphy, phyaddr, reg));
1090		else
1091			return (0xffff);
1092	}
1093
1094	/* local phy: our emac controls our phy */
1095
1096	regs = ch->regs;
1097
1098	/* clear mii_int */
1099	W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1100
1101	/* issue the read */
1102	W_REG(ch->osh, &regs->mdiodata,  (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT)
1103		| (reg << MD_RA_SHIFT) | MD_TA_VALID));
1104
1105	/* wait for it to complete */
1106	SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
1107	if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1108		ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
1109	}
1110
1111	return (R_REG(ch->osh, &regs->mdiodata) & MD_DATA_MASK);
1112}
1113
1114static void
1115chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1116{
1117	bcmenetregs_t *regs;
1118
1119	ASSERT(phyaddr < MAXEPHY);
1120
1121	/*
1122	 * BCM5222 dualphy shared mdio contortion.
1123	 * remote phy: another emac controls our phy.
1124	 */
1125	if (ch->etc->mdcport != ch->etc->coreunit) {
1126		if (ch->etphy == NULL)
1127			ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
1128		if (ch->etphy)
1129			et_phywr(ch->etphy, phyaddr, reg, v);
1130		return;
1131	}
1132
1133	/* local phy: our emac controls our phy */
1134
1135	regs = ch->regs;
1136
1137	/* clear mii_int */
1138	W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1139	ASSERT((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0);
1140
1141	/* issue the write */
1142	W_REG(ch->osh, &regs->mdiodata,  (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT)
1143		| (reg << MD_RA_SHIFT) | MD_TA_VALID | v));
1144
1145	/* wait for it to complete */
1146	SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
1147	if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1148		ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
1149	}
1150}
1151
1152static void
1153chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1154{
1155	uint16 tmp;
1156
1157	tmp = chipphyrd(ch, phyaddr, reg);
1158	tmp |= v;
1159	chipphywr(ch, phyaddr, reg, tmp);
1160}
1161
1162static void
1163chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1164{
1165	uint16 tmp;
1166
1167	tmp = chipphyrd(ch, phyaddr, reg);
1168	tmp &= v;
1169	chipphywr(ch, phyaddr, reg, tmp);
1170}
1171
1172static void
1173chipphyreset(struct bcm4xxx *ch, uint phyaddr)
1174{
1175	ASSERT(phyaddr < MAXEPHY);
1176
1177	if (phyaddr == EPHY_NOREG)
1178		return;
1179
1180	chipphywr(ch, phyaddr, 0, CTL_RESET);
1181	OSL_DELAY(100);
1182	if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) {
1183		ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit));
1184	}
1185
1186	chipphyinit(ch, phyaddr);
1187}
1188
1189static void
1190chipphyinit(struct bcm4xxx *ch, uint phyaddr)
1191{
1192	uint	phyid = 0;
1193
1194	/* enable activity led */
1195	chipphyand(ch, phyaddr, 26, 0x7fff);
1196
1197	/* enable traffic meter led mode */
1198	chipphyor(ch, phyaddr, 27, (1 << 6));
1199
1200	phyid = chipphyrd(ch, phyaddr, 0x2);
1201	phyid |=  chipphyrd(ch, phyaddr, 0x3) << 16;
1202	if (phyid == 0x55210022) {
1203		chipphywr(ch, phyaddr, 30, (uint16) (chipphyrd(ch, phyaddr, 30) | 0x3000));
1204		chipphywr(ch, phyaddr, 22, (uint16) (chipphyrd(ch, phyaddr, 22) & 0xffdf));
1205	}
1206}
1207
1208static void
1209chipphyforce(struct bcm4xxx *ch, uint phyaddr)
1210{
1211	etc_info_t *etc;
1212	uint16 ctl;
1213
1214	ASSERT(phyaddr < MAXEPHY);
1215
1216	if (phyaddr == EPHY_NOREG)
1217		return;
1218
1219	etc = ch->etc;
1220
1221	if (etc->forcespeed == ET_AUTO)
1222		return;
1223
1224	ctl = chipphyrd(ch, phyaddr, 0);
1225	ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX);
1226
1227	switch (etc->forcespeed) {
1228	case ET_10HALF:
1229		break;
1230
1231	case ET_10FULL:
1232		ctl |= CTL_DUPLEX;
1233		break;
1234
1235	case ET_100HALF:
1236		ctl |= CTL_SPEED;
1237		break;
1238
1239	case ET_100FULL:
1240		ctl |= (CTL_SPEED | CTL_DUPLEX);
1241		break;
1242	}
1243
1244	chipphywr(ch, phyaddr, 0, ctl);
1245}
1246
1247/* set selected capability bits in autonegotiation advertisement */
1248static void
1249chipphyadvertise(struct bcm4xxx *ch, uint phyaddr)
1250{
1251	etc_info_t *etc;
1252	uint16 adv;
1253
1254	ASSERT(phyaddr < MAXEPHY);
1255
1256	if (phyaddr == EPHY_NOREG)
1257		return;
1258
1259	etc = ch->etc;
1260
1261	if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
1262		return;
1263
1264	ASSERT(etc->advertise);
1265
1266	/* reset our advertised capabilitity bits */
1267	adv = chipphyrd(ch, phyaddr, 4);
1268	adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
1269	adv |= etc->advertise;
1270	chipphywr(ch, phyaddr, 4, adv);
1271
1272	/* restart autonegotiation */
1273	chipphyor(ch, phyaddr, 0, CTL_RESTART);
1274
1275	etc->needautoneg = FALSE;
1276}
1277