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