BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / et / sys / etc47xx.c
blob7ccd648f9130227f3842fcd08274135bd269166d
1 /*
2 * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core.
4 * This file implements the chip-specific routines
5 * for Broadcom HNBU Sonics SiliconBackplane enet cores.
7 * Copyright (C) 2011, 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.
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 286404 2011-09-27 19:29:08Z $
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 */
39 #ifdef ETROBO
40 #include <bcmrobo.h>
41 #endif /* ETROBO */
42 #ifdef ETADM
43 #include <etc_adm.h>
44 #endif /* ETADM */
46 struct bcm4xxx; /* forward declaration */
47 #define ch_t struct bcm4xxx
48 #include <etc.h>
50 /* private chip state */
51 struct bcm4xxx {
52 void *et; /* pointer to et private state */
53 etc_info_t *etc; /* pointer to etc public state */
55 bcmenetregs_t *regs; /* pointer to chip registers */
56 osl_t *osh; /* os handle */
58 void *etphy; /* pointer to et for shared mdc/mdio contortion */
60 uint32 intstatus; /* saved interrupt condition bits */
61 uint32 intmask; /* current software interrupt mask */
63 hnddma_t *di; /* dma engine software state */
65 bool mibgood; /* true once mib registers have been cleared */
66 bcmenetmib_t mib; /* mib counters */
67 si_t *sih; /* si utils handle */
69 char *vars; /* sprom name=value */
70 uint vars_size;
72 void *adm; /* optional admtek private data */
75 /* local prototypes */
76 static bool chipid(uint vendor, uint device);
77 static void *chipattach(etc_info_t *etc, void *osh, void *regsva);
78 static void chipdetach(ch_t *ch);
79 static void chipreset(ch_t *ch);
80 static void chipinit(ch_t *ch, uint options);
81 static bool chiptx(ch_t *ch, void *p);
82 static void *chiprx(ch_t *ch);
83 static void chiprxfill(ch_t *ch);
84 static int chipgetintrevents(ch_t *ch, bool in_isr);
85 static bool chiperrors(ch_t *ch);
86 static void chipintrson(ch_t *ch);
87 static void chipintrsoff(ch_t *ch);
88 static void chiptxreclaim(ch_t *ch, bool all);
89 static void chiprxreclaim(ch_t *ch);
90 static void chipstatsupd(ch_t *ch);
91 static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear);
92 static void chipenablepme(ch_t *ch);
93 static void chipdisablepme(ch_t *ch);
94 static void chipphyreset(ch_t *ch, uint phyaddr);
95 static void chipphyinit(ch_t *ch, uint phyaddr);
96 static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg);
97 static void chipdump(ch_t *ch, struct bcmstrbuf *b);
98 static void chiplongname(ch_t *ch, char *buf, uint bufsize);
99 static void chipduplexupd(ch_t *ch);
100 static void chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex);
101 static void chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
102 static void chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
103 static void chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
104 static void chipphyforce(struct bcm4xxx *ch, uint phyaddr);
105 static void chipphyadvertise(struct bcm4xxx *ch, uint phyaddr);
106 #ifdef BCMDBG
107 static void chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, struct bcmstrbuf *b);
108 #endif /* BCMDBG */
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)
114 struct 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 chipintrson,
126 chipintrsoff,
127 chiptxreclaim,
128 chiprxreclaim,
129 chipstatsupd,
130 chipdumpmib,
131 chipenablepme,
132 chipdisablepme,
133 chipphyreset,
134 chipphyrd,
135 chipphywr,
136 chipdump,
137 chiplongname,
138 chipduplexupd
141 static uint devices[] = {
142 BCM47XX_ENET_ID,
143 0x0000 };
145 static bool
146 chipid(uint vendor, uint device)
148 int i;
150 if (vendor != VENDOR_BROADCOM)
151 return (FALSE);
153 for (i = 0; devices[i]; i++) {
154 if (device == devices[i])
155 return (TRUE);
157 return (FALSE);
160 static void *
161 chipattach(etc_info_t *etc, void *osh, void *regsva)
163 struct bcm4xxx *ch;
164 bcmenetregs_t *regs;
165 char name[16];
166 char *var;
167 uint boardflags, boardtype;
169 ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva));
171 if ((ch = (struct bcm4xxx *)MALLOC(osh, sizeof(struct bcm4xxx))) == NULL) {
172 ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit,
173 MALLOCED(osh)));
174 return (NULL);
176 bzero((char *)ch, sizeof(struct bcm4xxx));
178 ch->etc = etc;
179 ch->et = etc->et;
180 ch->osh = osh;
182 /* store the pointer to the sw mib */
183 etc->mib = (void *)&ch->mib;
185 /* get si handle */
186 if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars,
187 &ch->vars_size)) == NULL) {
188 ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit));
189 goto fail;
192 /* We used to have an assert here like:
193 * si_coreid(ch->sih) == ENET_CORE_ID
194 * but srom-less systems and simulators don't have a way to
195 * provide a default bar0window so we were relying on nvram
196 * variables. At some point we decided that we could do away
197 * with that since the wireless driver was simply doing a
198 * setcore in attach. So we need to do the same here for
199 * the ethernet.
201 if ((regs = (bcmenetregs_t *)si_setcore(ch->sih, ENET_CORE_ID, etc->unit)) == NULL) {
202 ET_ERROR(("et%d: chipattach: Could not setcore to the ENET core\n", etc->unit));
203 goto fail;
206 ch->regs = regs;
207 etc->chip = ch->sih->chip;
208 etc->chiprev = ch->sih->chiprev;
209 etc->coreid = si_coreid(ch->sih);
210 etc->corerev = si_corerev(ch->sih);
211 etc->nicmode = !(ch->sih->bustype == SI_BUS);
212 etc->coreunit = si_coreunit(ch->sih);
213 etc->boardflags = getintvar(ch->vars, "boardflags");
215 boardflags = etc->boardflags;
216 boardtype = ch->sih->boardtype;
218 /* get our local ether addr */
219 sprintf(name, "et%dmacaddr", etc->coreunit);
220 var = getvar(ch->vars, name);
221 if (var == NULL) {
222 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
223 goto fail;
225 bcm_ether_atoe(var, &etc->perm_etheraddr);
227 if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) {
228 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var));
229 goto fail;
231 bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN);
234 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
235 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
238 /* get our phyaddr value */
239 sprintf(name, "et%dphyaddr", etc->coreunit);
240 var = getvar(ch->vars, name);
241 if (var == NULL) {
242 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
243 goto fail;
245 etc->phyaddr = bcm_atoi(var) & EPHY_MASK;
247 /* nvram says no phy is present */
248 if (etc->phyaddr == EPHY_NONE) {
249 ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit));
250 goto fail;
253 /* get our mdc/mdio port number */
254 sprintf(name, "et%dmdcport", etc->coreunit);
255 var = getvar(ch->vars, name);
256 if (var == NULL) {
257 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
258 goto fail;
260 etc->mdcport = bcm_atoi(var);
262 /* configure pci core */
263 si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
265 /* reset the enet core */
266 chipreset(ch);
268 /* dma attach */
269 sprintf(name, "et%d", etc->coreunit);
270 if ((ch->di = dma_attach(osh, name, ch->sih,
271 (void *)&regs->dmaregs.xmt, (void *)&regs->dmaregs.rcv,
272 NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF,
273 &et_msg_level)) == NULL) {
274 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit));
275 goto fail;
277 etc->txavail[TX_Q0] = (uint *)&ch->di->txavail;
279 /* set default sofware intmask */
280 ch->intmask = DEF_INTMASK;
283 * For the 5222 dual phy shared mdio contortion, our phy is
284 * on someone elses mdio pins. This other enet enet
285 * may not yet be attached so we must defer the et_phyfind().
287 /* if local phy: reset it once now */
288 if (etc->mdcport == etc->coreunit)
289 chipphyreset(ch, etc->phyaddr);
291 #ifdef ETROBO
293 * Broadcom Robo ethernet switch.
295 if ((boardflags & BFL_ENETROBO) &&
296 (etc->phyaddr == EPHY_NOREG)) {
297 /* Attach to the switch */
298 if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars,
299 (miird_f)bcm47xx_et_chops.phyrd,
300 (miiwr_f)bcm47xx_et_chops.phywr))) {
301 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit));
302 goto fail;
304 /* Enable the switch and set it to a known good state */
305 if (bcm_robo_enable_device(etc->robo)) {
306 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit));
307 goto fail;
309 /* Configure the switch to do VLAN */
310 if ((boardflags & BFL_ENETVLAN) &&
311 bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) {
312 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit));
313 goto fail;
315 /* Enable switching/forwarding */
316 if (bcm_robo_enable_switch(etc->robo)) {
317 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit));
318 goto fail;
321 #endif /* ETROBO */
323 #ifdef ETADM
325 * ADMtek ethernet switch.
327 if (boardflags & BFL_ENETADM) {
328 /* Attach to the device */
329 if (!(ch->adm = adm_attach(ch->sih, ch->vars))) {
330 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc->unit));
331 goto fail;
333 /* Enable the external switch and set it to a known good state */
334 if (adm_enable_device(ch->adm)) {
335 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc->unit));
336 goto fail;
338 /* Configure the switch */
339 if ((boardflags & BFL_ENETVLAN) && adm_config_vlan(ch->adm)) {
340 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc->unit));
341 goto fail;
344 #endif /* ETADM */
346 return ((void *)ch);
348 fail:
349 chipdetach(ch);
350 return (NULL);
353 static void
354 chipdetach(struct bcm4xxx *ch)
356 ET_TRACE(("et%d: chipdetach\n", ch->etc->unit));
358 if (ch == NULL)
359 return;
361 #ifdef ETROBO
362 /* free robo state */
363 if (ch->etc->robo)
364 bcm_robo_detach(ch->etc->robo);
365 #endif /* ETROBO */
367 #ifdef ETADM
368 /* free ADMtek state */
369 if (ch->adm)
370 adm_detach(ch->adm);
371 #endif /* ETADM */
373 /* free dma state */
374 if (ch->di)
375 dma_detach(ch->di);
376 ch->di = NULL;
378 /* put the core back into reset */
379 if (ch->sih)
380 si_core_disable(ch->sih, 0);
382 /* free si handle */
383 si_detach(ch->sih);
384 ch->sih = NULL;
386 /* free vars */
387 if (ch->vars)
388 MFREE(ch->osh, ch->vars, ch->vars_size);
390 /* free chip private state */
391 MFREE(ch->osh, ch, sizeof(struct bcm4xxx));
394 static void
395 chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize)
397 char *s;
399 switch (ch->etc->deviceid) {
400 case BCM47XX_ENET_ID:
401 default:
402 s = "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
403 break;
406 strncpy(buf, s, bufsize);
407 buf[bufsize - 1] = '\0';
410 static void
411 chipdump(struct bcm4xxx *ch, struct bcmstrbuf *b)
413 #ifdef BCMDBG
414 bcm_bprintf(b, "regs 0x%x etphy 0x%x ch->intstatus 0x%x intmask 0x%x\n",
415 (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask);
416 bcm_bprintf(b, "\n");
418 /* dma engine state */
419 dma_dump(ch->di, b, FALSE);
420 bcm_bprintf(b, "\n");
422 /* registers */
423 chipdumpregs(ch, ch->regs, b);
424 bcm_bprintf(b, "\n");
426 /* switch registers */
427 #ifdef ETROBO
428 if (ch->etc->robo)
429 robo_dump_regs(ch->etc->robo, b);
430 #endif /* ETROBO */
431 #ifdef ETADM
432 if (ch->adm)
433 adm_dump_regs(ch->adm, b->buf);
434 #endif /* ETADM */
435 #endif /* BCMDBG */
438 #ifdef BCMDBG
440 #define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->name))
441 #define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->mib.name))
443 static void
444 chipdumpregs(struct bcm4xxx *ch, bcmenetregs_t *regs, struct bcmstrbuf *b)
446 uint phyaddr;
448 phyaddr = ch->etc->phyaddr;
450 PRREG(devcontrol); PRREG(biststatus); PRREG(wakeuplength);
451 bcm_bprintf(b, "\n");
452 PRREG(intstatus); PRREG(intmask); PRREG(gptimer);
453 bcm_bprintf(b, "\n");
454 PRREG(emactxmaxburstlen); PRREG(emacrxmaxburstlen);
455 PRREG(emaccontrol); PRREG(emacflowcontrol);
456 bcm_bprintf(b, "\n");
457 PRREG(intrecvlazy);
458 bcm_bprintf(b, "\n");
460 /* emac registers */
461 PRREG(rxconfig); PRREG(rxmaxlength); PRREG(txmaxlength);
462 bcm_bprintf(b, "\n");
463 PRREG(mdiocontrol); PRREG(camcontrol); PRREG(enetcontrol);
464 bcm_bprintf(b, "\n");
465 PRREG(txcontrol); PRREG(txwatermark); PRREG(mibcontrol);
466 bcm_bprintf(b, "\n");
468 /* mib registers */
469 PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts);
470 bcm_bprintf(b, "\n");
471 PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts);
472 bcm_bprintf(b, "\n");
473 PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts);
474 bcm_bprintf(b, "\n");
475 PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols);
476 bcm_bprintf(b, "\n");
477 PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols);
478 bcm_bprintf(b, "\n");
479 PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts);
480 bcm_bprintf(b, "\n");
482 PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts);
483 bcm_bprintf(b, "\n");
484 PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts);
485 bcm_bprintf(b, "\n");
486 PRMIBREG(rx_jabber_pkts); PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts);
487 bcm_bprintf(b, "\n");
488 PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize);
489 bcm_bprintf(b, "\n");
490 PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs);
491 bcm_bprintf(b, "\n");
492 PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts);
493 bcm_bprintf(b, "\n");
495 if (phyaddr != EPHY_NOREG) {
496 /* print a few interesting phy registers */
497 bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n",
498 chipphyrd(ch, phyaddr, 0),
499 chipphyrd(ch, phyaddr, 1),
500 chipphyrd(ch, phyaddr, 2),
501 chipphyrd(ch, phyaddr, 3));
502 bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n",
503 chipphyrd(ch, phyaddr, 4),
504 chipphyrd(ch, phyaddr, 5),
505 chipphyrd(ch, phyaddr, 24),
506 chipphyrd(ch, phyaddr, 25));
510 #endif /* BCMDBG */
512 #define MDC_RATIO 5000000
514 static void
515 chipreset(struct bcm4xxx *ch)
517 bcmenetregs_t *regs;
518 uint32 clk, mdc;
520 ET_TRACE(("et%d: chipreset\n", ch->etc->unit));
522 regs = ch->regs;
524 if (!si_iscoreup(ch->sih)) {
525 if (!ch->etc->nicmode)
526 si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
527 /* power on reset: reset the enet core */
528 si_core_reset(ch->sih, 0, 0);
529 goto chipinreset;
532 /* read counters before resetting the chip */
533 if (ch->mibgood)
534 chipstatsupd(ch);
536 /* reset the tx dma engine */
537 if (ch->di)
538 dma_txreset(ch->di);
540 /* set emac into loopback mode to ensure no rx traffic */
541 W_REG(ch->osh, &regs->rxconfig, ERC_LE);
542 OSL_DELAY(1);
544 /* reset the rx dma engine */
545 if (ch->di)
546 dma_rxreset(ch->di);
548 /* reset core */
549 si_core_reset(ch->sih, 0, 0);
551 chipinreset:
553 /* must clear mib registers by hand */
554 W_REG(ch->osh, &regs->mibcontrol, EMC_RZ);
555 (void) R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
556 (void) R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
557 (void) R_REG(ch->osh, &regs->mib.tx_len_64);
558 (void) R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
559 (void) R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
560 (void) R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
561 (void) R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
562 (void) R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
563 (void) R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
564 (void) R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
565 (void) R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
566 (void) R_REG(ch->osh, &regs->mib.tx_underruns);
567 (void) R_REG(ch->osh, &regs->mib.tx_total_cols);
568 (void) R_REG(ch->osh, &regs->mib.tx_single_cols);
569 (void) R_REG(ch->osh, &regs->mib.tx_multiple_cols);
570 (void) R_REG(ch->osh, &regs->mib.tx_excessive_cols);
571 (void) R_REG(ch->osh, &regs->mib.tx_late_cols);
572 (void) R_REG(ch->osh, &regs->mib.tx_defered);
573 (void) R_REG(ch->osh, &regs->mib.tx_carrier_lost);
574 (void) R_REG(ch->osh, &regs->mib.tx_pause_pkts);
575 (void) R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
576 (void) R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
577 (void) R_REG(ch->osh, &regs->mib.rx_len_64);
578 (void) R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
579 (void) R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
580 (void) R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
581 (void) R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
582 (void) R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
583 (void) R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
584 (void) R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
585 (void) R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
586 (void) R_REG(ch->osh, &regs->mib.rx_missed_pkts);
587 (void) R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
588 (void) R_REG(ch->osh, &regs->mib.rx_undersize);
589 (void) R_REG(ch->osh, &regs->mib.rx_crc_errs);
590 (void) R_REG(ch->osh, &regs->mib.rx_align_errs);
591 (void) R_REG(ch->osh, &regs->mib.rx_symbol_errs);
592 (void) R_REG(ch->osh, &regs->mib.rx_pause_pkts);
593 (void) R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
594 ch->mibgood = TRUE;
597 * We want the phy registers to be accessible even when
598 * the driver is "downed" so initialize MDC preamble, frequency,
599 * and whether internal or external phy here.
601 /* default: 100Mhz SI clock and external phy */
602 W_REG(ch->osh, &regs->mdiocontrol, 0x94);
603 if (ch->etc->deviceid == BCM47XX_ENET_ID) {
604 /* 47xx chips: find out the clock */
605 if ((clk = si_clock(ch->sih)) != 0) {
606 mdc = 0x80 | ((clk + (MDC_RATIO / 2)) / MDC_RATIO);
607 W_REG(ch->osh, &regs->mdiocontrol, mdc);
608 } else {
609 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
610 "using 100Mhz\n",
611 ch->etc->unit));
615 /* some chips have internal phy, some don't */
616 if (!(R_REG(ch->osh, &regs->devcontrol) & DC_IP)) {
617 W_REG(ch->osh, &regs->enetcontrol, EC_EP);
618 } else if (R_REG(ch->osh, &regs->devcontrol) & DC_ER) {
619 AND_REG(ch->osh, &regs->devcontrol, ~DC_ER);
620 OSL_DELAY(100);
621 chipphyinit(ch, ch->etc->phyaddr);
624 /* clear persistent sw intstatus */
625 ch->intstatus = 0;
629 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
630 * but leave the devcontrol tx and rx (fifos) disabled.
632 static void
633 chipinit(struct bcm4xxx *ch, uint options)
635 etc_info_t *etc;
636 bcmenetregs_t *regs;
637 uint idx;
638 uint i;
640 regs = ch->regs;
641 etc = ch->etc;
642 idx = 0;
644 ET_TRACE(("et%d: chipinit\n", etc->unit));
646 /* enable crc32 generation */
647 OR_REG(ch->osh, &regs->emaccontrol, EMC_CG);
649 /* enable one rx interrupt per received frame */
650 W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));
652 /* enable 802.3x tx flow control (honor received PAUSE frames) */
653 W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);
655 /* initialize CAM */
656 if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
657 OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
658 else {
659 /* our local address */
660 chipwrcam(ch, &etc->cur_etheraddr, idx++);
662 /* allmulti or a list of discrete multicast addresses */
663 if (etc->allmulti)
664 OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
665 else if (etc->nmulticast) {
666 for (i = 0; i < etc->nmulticast; i++)
667 chipwrcam(ch, &etc->multicast[i], idx++);
670 /* enable cam */
671 OR_REG(ch->osh, &regs->camcontrol, CC_CE);
674 /* optionally enable mac-level loopback */
675 if (etc->loopbk)
676 OR_REG(ch->osh, &regs->rxconfig, ERC_LE);
678 /* set max frame lengths - account for possible vlan tag */
679 W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
680 W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);
682 /* set tx watermark */
683 W_REG(ch->osh, &regs->txwatermark, 56);
686 * Optionally, disable phy autonegotiation and force our speed/duplex
687 * or constrain our advertised capabilities.
689 if (etc->forcespeed != ET_AUTO)
690 chipphyforce(ch, etc->phyaddr);
691 else if (etc->advertise && etc->needautoneg)
692 chipphyadvertise(ch, etc->phyaddr);
694 if (options & ET_INIT_FULL) {
695 /* initialize the tx and rx dma channels */
696 dma_txinit(ch->di);
697 dma_rxinit(ch->di);
699 /* post dma receive buffers */
700 dma_rxfill(ch->di);
702 /* lastly, enable interrupts */
703 if (options & ET_INIT_INTRON)
704 et_intrson(etc->et);
706 else
707 dma_rxenable(ch->di);
709 /* turn on the emac */
710 OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
713 /* dma transmit */
714 static bool BCMFASTPATH
715 chiptx(struct bcm4xxx *ch, void *p0)
717 int error;
719 ET_TRACE(("et%d: chiptx\n", ch->etc->unit));
720 ET_LOG("et%d: chiptx", ch->etc->unit, 0);
722 error = dma_txfast(ch->di, p0, TRUE);
724 if (error) {
725 ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit));
726 ch->etc->txnobuf++;
727 return FALSE;
729 return TRUE;
732 /* reclaim completed transmit descriptors and packets */
733 static void BCMFASTPATH
734 chiptxreclaim(struct bcm4xxx *ch, bool forceall)
736 ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit));
737 dma_txreclaim(ch->di, forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED);
738 ch->intstatus &= ~I_XI;
741 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
742 static void * BCMFASTPATH
743 chiprx(struct bcm4xxx *ch)
745 void *p;
747 ET_TRACE(("et%d: chiprx\n", ch->etc->unit));
748 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
750 if ((p = dma_rx(ch->di)) == NULL)
751 ch->intstatus &= ~I_RI;
753 return (p);
756 /* reclaim completed dma receive descriptors and packets */
757 static void
758 chiprxreclaim(struct bcm4xxx *ch)
760 ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit));
761 dma_rxreclaim(ch->di);
762 ch->intstatus &= ~I_RI;
765 /* allocate and post dma receive buffers */
766 static void BCMFASTPATH
767 chiprxfill(struct bcm4xxx *ch)
769 ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit));
770 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
771 dma_rxfill(ch->di);
774 /* get current and pending interrupt events */
775 static int BCMFASTPATH
776 chipgetintrevents(struct bcm4xxx *ch, bool in_isr)
778 bcmenetregs_t *regs;
779 uint32 intstatus;
780 int events;
782 regs = ch->regs;
783 events = 0;
785 /* read the interrupt status register */
786 intstatus = R_REG(ch->osh, &regs->intstatus);
788 /* defer unsolicited interrupts */
789 intstatus &= (in_isr ? ch->intmask : DEF_INTMASK);
791 /* clear non-error interrupt conditions */
792 if (intstatus != 0) {
793 W_REG(ch->osh, &regs->intstatus, intstatus);
794 events = INTR_NEW;
797 /* or new bits into persistent intstatus */
798 intstatus = (ch->intstatus |= intstatus);
800 /* return if no events */
801 if (intstatus == 0)
802 return (0);
804 /* convert chip-specific intstatus bits into generic intr event bits */
805 if (intstatus & I_RI)
806 events |= INTR_RX;
807 if (intstatus & I_XI)
808 events |= INTR_TX;
809 if (intstatus & I_ERRORS)
810 events |= INTR_ERROR;
811 if (intstatus & I_TO)
812 events |= INTR_TO;
814 return (events);
817 /* enable chip interrupts */
818 static void BCMFASTPATH
819 chipintrson(struct bcm4xxx *ch)
821 ch->intmask = DEF_INTMASK;
822 W_REG(ch->osh, &ch->regs->intmask, ch->intmask);
825 /* disable chip interrupts */
826 static void BCMFASTPATH
827 chipintrsoff(struct bcm4xxx *ch)
829 W_REG(ch->osh, &ch->regs->intmask, 0);
830 (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */
831 ch->intmask = 0;
834 /* return true of caller should re-initialize, otherwise false */
835 static bool BCMFASTPATH
836 chiperrors(struct bcm4xxx *ch)
838 uint32 intstatus;
839 etc_info_t *etc;
841 etc = ch->etc;
843 intstatus = ch->intstatus;
844 ch->intstatus &= ~(I_ERRORS);
846 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus));
848 if (intstatus & I_PC) {
849 ET_ERROR(("et%d: descriptor error\n", etc->unit));
850 etc->dmade++;
853 if (intstatus & I_PD) {
854 ET_ERROR(("et%d: data error\n", etc->unit));
855 etc->dmada++;
858 if (intstatus & I_DE) {
859 ET_ERROR(("et%d: descriptor protocol error\n", etc->unit));
860 etc->dmape++;
862 /* NOTE : this ie NOT an error. It becomes an error only
863 * when the rx fifo overflows
865 if (intstatus & I_RU) {
866 ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit));
867 etc->rxdmauflo++;
870 if (intstatus & I_RO) {
871 ET_ERROR(("et%d: receive fifo overflow\n", etc->unit));
872 etc->rxoflo++;
875 if (intstatus & I_XU) {
876 ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit));
877 etc->txuflo++;
879 /* if overflows or decriptors underflow, don't report it
880 * as an error and provoque a reset
882 if (intstatus & ~(I_RU) & I_ERRORS)
883 return (TRUE);
884 return FALSE;
887 static void
888 chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
890 uint32 w;
892 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0);
894 w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8)
895 | ea->octet[5];
896 W_REG(ch->osh, &ch->regs->camdatalo, w);
897 w = CD_V | (ea->octet[0] << 8) | ea->octet[1];
898 W_REG(ch->osh, &ch->regs->camdatahi, w);
899 W_REG(ch->osh, &ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR));
901 /* spin until done */
902 SPINWAIT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB), 1000);
905 * This assertion is usually caused by the phy not providing a clock
906 * to the bottom portion of the mac..
908 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB) == 0);
911 static void
912 chipstatsupd(struct bcm4xxx *ch)
914 etc_info_t *etc;
915 bcmenetregs_t *regs;
916 bcmenetmib_t *m;
918 etc = ch->etc;
919 regs = ch->regs;
920 m = &ch->mib;
923 * mib counters are clear-on-read.
924 * Don't bother using the pkt and octet counters since they are only
925 * 16bits and wrap too quickly to be useful.
927 m->tx_broadcast_pkts += R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
928 m->tx_multicast_pkts += R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
929 m->tx_len_64 += R_REG(ch->osh, &regs->mib.tx_len_64);
930 m->tx_len_65_to_127 += R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
931 m->tx_len_128_to_255 += R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
932 m->tx_len_256_to_511 += R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
933 m->tx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
934 m->tx_len_1024_to_max += R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
935 m->tx_jabber_pkts += R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
936 m->tx_oversize_pkts += R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
937 m->tx_fragment_pkts += R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
938 m->tx_underruns += R_REG(ch->osh, &regs->mib.tx_underruns);
939 m->tx_total_cols += R_REG(ch->osh, &regs->mib.tx_total_cols);
940 m->tx_single_cols += R_REG(ch->osh, &regs->mib.tx_single_cols);
941 m->tx_multiple_cols += R_REG(ch->osh, &regs->mib.tx_multiple_cols);
942 m->tx_excessive_cols += R_REG(ch->osh, &regs->mib.tx_excessive_cols);
943 m->tx_late_cols += R_REG(ch->osh, &regs->mib.tx_late_cols);
944 m->tx_defered += R_REG(ch->osh, &regs->mib.tx_defered);
945 m->tx_carrier_lost += R_REG(ch->osh, &regs->mib.tx_carrier_lost);
946 m->tx_pause_pkts += R_REG(ch->osh, &regs->mib.tx_pause_pkts);
947 m->rx_broadcast_pkts += R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
948 m->rx_multicast_pkts += R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
949 m->rx_len_64 += R_REG(ch->osh, &regs->mib.rx_len_64);
950 m->rx_len_65_to_127 += R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
951 m->rx_len_128_to_255 += R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
952 m->rx_len_256_to_511 += R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
953 m->rx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
954 m->rx_len_1024_to_max += R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
955 m->rx_jabber_pkts += R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
956 m->rx_oversize_pkts += R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
957 m->rx_fragment_pkts += R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
958 m->rx_missed_pkts += R_REG(ch->osh, &regs->mib.rx_missed_pkts);
959 m->rx_crc_align_errs += R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
960 m->rx_undersize += R_REG(ch->osh, &regs->mib.rx_undersize);
961 m->rx_crc_errs += R_REG(ch->osh, &regs->mib.rx_crc_errs);
962 m->rx_align_errs += R_REG(ch->osh, &regs->mib.rx_align_errs);
963 m->rx_symbol_errs += R_REG(ch->osh, &regs->mib.rx_symbol_errs);
964 m->rx_pause_pkts += R_REG(ch->osh, &regs->mib.rx_pause_pkts);
965 m->rx_nonpause_pkts += R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
968 * Aggregate transmit and receive errors that probably resulted
969 * in the loss of a frame are computed on the fly.
971 * We seem to get lots of tx_carrier_lost errors when flipping
972 * speed modes so don't count these as tx errors.
974 * Arbitrarily lump the non-specific dma errors as tx errors.
976 etc->txerror = m->tx_jabber_pkts + m->tx_oversize_pkts
977 + m->tx_underruns + m->tx_excessive_cols
978 + m->tx_late_cols + etc->txnobuf + etc->dmade
979 + etc->dmada + etc->dmape + etc->txuflo;
980 etc->rxerror = m->rx_jabber_pkts + m->rx_oversize_pkts
981 + m->rx_missed_pkts + m->rx_crc_align_errs
982 + m->rx_undersize + m->rx_crc_errs
983 + m->rx_align_errs + m->rx_symbol_errs
984 + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen;
987 static void
988 chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear)
990 bcmenetmib_t *m;
992 m = &ch->mib;
994 if (clear) {
995 bzero((char *)m, sizeof(bcmenetmib_t));
996 return;
999 bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d "
1000 "tx_oversize_pkts %d\n",
1001 m->tx_broadcast_pkts, m->tx_multicast_pkts,
1002 m->tx_jabber_pkts,
1003 m->tx_oversize_pkts);
1004 bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n",
1005 m->tx_fragment_pkts, m->tx_underruns);
1006 bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d "
1007 "tx_excessive_cols %d\n",
1008 m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols,
1009 m->tx_excessive_cols);
1010 bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n",
1011 m->tx_late_cols, m->tx_defered, m->tx_carrier_lost,
1012 m->tx_pause_pkts);
1014 /* receive stat counters */
1015 /* hardware mib pkt and octet counters wrap too quickly to be useful */
1016 bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d "
1017 "rx_oversize_pkts %d\n",
1018 m->rx_broadcast_pkts, m->rx_multicast_pkts,
1019 m->rx_jabber_pkts, m->rx_oversize_pkts);
1020 bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d "
1021 "rx_undersize %d\n",
1022 m->rx_fragment_pkts, m->rx_missed_pkts,
1023 m->rx_crc_align_errs, m->rx_undersize);
1024 bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n",
1025 m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs);
1026 bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n",
1027 m->rx_pause_pkts, m->rx_nonpause_pkts);
1030 static void
1031 chipenablepme(struct bcm4xxx *ch)
1033 bcmenetregs_t *regs;
1035 regs = ch->regs;
1037 /* enable chip wakeup pattern matching */
1038 OR_REG(ch->osh, &regs->devcontrol, DC_PM);
1040 /* enable sonics bus PME */
1041 si_core_cflags(ch->sih, SICF_PME_EN, SICF_PME_EN);
1044 static void
1045 chipdisablepme(struct bcm4xxx *ch)
1047 bcmenetregs_t *regs;
1049 regs = ch->regs;
1051 AND_REG(ch->osh, &regs->devcontrol, ~DC_PM);
1052 si_core_cflags(ch->sih, SICF_PME_EN, 0);
1055 static void
1056 chipduplexupd(struct bcm4xxx *ch)
1058 uint32 txcontrol;
1060 txcontrol = R_REG(ch->osh, &ch->regs->txcontrol);
1061 if (ch->etc->duplex && !(txcontrol & EXC_FD))
1062 OR_REG(ch->osh, &ch->regs->txcontrol, EXC_FD);
1063 else if (!ch->etc->duplex && (txcontrol & EXC_FD))
1064 AND_REG(ch->osh, &ch->regs->txcontrol, ~EXC_FD);
1067 static uint16
1068 chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg)
1070 bcmenetregs_t *regs;
1072 ASSERT(phyaddr < MAXEPHY);
1075 * BCM5222 dualphy shared mdio contortion.
1076 * remote phy: another emac controls our phy.
1078 if (ch->etc->mdcport != ch->etc->coreunit) {
1079 if (ch->etphy == NULL) {
1080 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
1082 /* first time reset */
1083 if (ch->etphy)
1084 chipphyreset(ch, ch->etc->phyaddr);
1086 if (ch->etphy)
1087 return (et_phyrd(ch->etphy, phyaddr, reg));
1088 else
1089 return (0xffff);
1092 /* local phy: our emac controls our phy */
1094 regs = ch->regs;
1096 /* clear mii_int */
1097 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1099 /* issue the read */
1100 W_REG(ch->osh, &regs->mdiodata, (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT)
1101 | (reg << MD_RA_SHIFT) | MD_TA_VALID));
1103 /* wait for it to complete */
1104 SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
1105 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1106 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
1109 return (R_REG(ch->osh, &regs->mdiodata) & MD_DATA_MASK);
1112 static void
1113 chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1115 bcmenetregs_t *regs;
1117 ASSERT(phyaddr < MAXEPHY);
1120 * BCM5222 dualphy shared mdio contortion.
1121 * remote phy: another emac controls our phy.
1123 if (ch->etc->mdcport != ch->etc->coreunit) {
1124 if (ch->etphy == NULL)
1125 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
1126 if (ch->etphy)
1127 et_phywr(ch->etphy, phyaddr, reg, v);
1128 return;
1131 /* local phy: our emac controls our phy */
1133 regs = ch->regs;
1135 /* clear mii_int */
1136 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1137 ASSERT((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0);
1139 /* issue the write */
1140 W_REG(ch->osh, &regs->mdiodata, (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT)
1141 | (reg << MD_RA_SHIFT) | MD_TA_VALID | v));
1143 /* wait for it to complete */
1144 SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
1145 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1146 ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
1150 static void
1151 chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1153 uint16 tmp;
1155 tmp = chipphyrd(ch, phyaddr, reg);
1156 tmp |= v;
1157 chipphywr(ch, phyaddr, reg, tmp);
1160 static void
1161 chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1163 uint16 tmp;
1165 tmp = chipphyrd(ch, phyaddr, reg);
1166 tmp &= v;
1167 chipphywr(ch, phyaddr, reg, tmp);
1170 static void
1171 chipphyreset(struct bcm4xxx *ch, uint phyaddr)
1173 ASSERT(phyaddr < MAXEPHY);
1175 if (phyaddr == EPHY_NOREG)
1176 return;
1178 chipphywr(ch, phyaddr, 0, CTL_RESET);
1179 OSL_DELAY(100);
1180 if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) {
1181 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit));
1184 chipphyinit(ch, phyaddr);
1187 static void
1188 chipphyinit(struct bcm4xxx *ch, uint phyaddr)
1190 uint phyid = 0;
1192 /* enable activity led */
1193 chipphyand(ch, phyaddr, 26, 0x7fff);
1195 /* enable traffic meter led mode */
1196 chipphyor(ch, phyaddr, 27, (1 << 6));
1198 phyid = chipphyrd(ch, phyaddr, 0x2);
1199 phyid |= chipphyrd(ch, phyaddr, 0x3) << 16;
1200 if (phyid == 0x55210022) {
1201 chipphywr(ch, phyaddr, 30, (uint16) (chipphyrd(ch, phyaddr, 30) | 0x3000));
1202 chipphywr(ch, phyaddr, 22, (uint16) (chipphyrd(ch, phyaddr, 22) & 0xffdf));
1206 static void
1207 chipphyforce(struct bcm4xxx *ch, uint phyaddr)
1209 etc_info_t *etc;
1210 uint16 ctl;
1212 ASSERT(phyaddr < MAXEPHY);
1214 if (phyaddr == EPHY_NOREG)
1215 return;
1217 etc = ch->etc;
1219 if (etc->forcespeed == ET_AUTO)
1220 return;
1222 ctl = chipphyrd(ch, phyaddr, 0);
1223 ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX);
1225 switch (etc->forcespeed) {
1226 case ET_10HALF:
1227 break;
1229 case ET_10FULL:
1230 ctl |= CTL_DUPLEX;
1231 break;
1233 case ET_100HALF:
1234 ctl |= CTL_SPEED;
1235 break;
1237 case ET_100FULL:
1238 ctl |= (CTL_SPEED | CTL_DUPLEX);
1239 break;
1242 chipphywr(ch, phyaddr, 0, ctl);
1245 /* set selected capability bits in autonegotiation advertisement */
1246 static void
1247 chipphyadvertise(struct bcm4xxx *ch, uint phyaddr)
1249 etc_info_t *etc;
1250 uint16 adv;
1252 ASSERT(phyaddr < MAXEPHY);
1254 if (phyaddr == EPHY_NOREG)
1255 return;
1257 etc = ch->etc;
1259 if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
1260 return;
1262 ASSERT(etc->advertise);
1264 /* reset our advertised capabilitity bits */
1265 adv = chipphyrd(ch, phyaddr, 4);
1266 adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
1267 adv |= etc->advertise;
1268 chipphywr(ch, phyaddr, 4, adv);
1270 /* restart autonegotiation */
1271 chipphyor(ch, phyaddr, 0, CTL_RESTART);
1273 etc->needautoneg = FALSE;