Line data Source code
1 : /* $OpenBSD: if_lii.c,v 1.44 2017/01/22 10:17:38 dlg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007 The NetBSD Foundation.
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 : * POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : /*
30 : * Driver for Attansic/Atheros's L2 Fast Ethernet controller
31 : */
32 :
33 : #include "bpfilter.h"
34 :
35 : #include <sys/param.h>
36 : #include <sys/systm.h>
37 : #include <sys/sockio.h>
38 : #include <sys/mbuf.h>
39 : #include <sys/kernel.h>
40 : #include <sys/socket.h>
41 : #include <sys/malloc.h>
42 : #include <sys/device.h>
43 : #include <sys/timeout.h>
44 :
45 : #include <machine/bus.h>
46 :
47 : #include <net/if.h>
48 : #include <net/if_media.h>
49 :
50 : #if NBPFILTER > 0
51 : #include <net/bpf.h>
52 : #endif
53 :
54 : #include <netinet/in.h>
55 : #include <netinet/if_ether.h>
56 :
57 : #include <dev/mii/miivar.h>
58 :
59 : #include <dev/pci/pcireg.h>
60 : #include <dev/pci/pcivar.h>
61 : #include <dev/pci/pcidevs.h>
62 :
63 : #include <dev/pci/if_liireg.h>
64 :
65 : /*#define LII_DEBUG*/
66 : #ifdef LII_DEBUG
67 : #define DPRINTF(x) printf x
68 : #else
69 : #define DPRINTF(x)
70 : #endif
71 :
72 : struct lii_softc {
73 : struct device sc_dev;
74 : pci_chipset_tag_t sc_pc;
75 : pcitag_t sc_tag;
76 :
77 : bus_space_tag_t sc_mmiot;
78 : bus_space_handle_t sc_mmioh;
79 : bus_size_t sc_mmios;
80 :
81 : /*
82 : * We allocate a big chunk of DMA-safe memory for all data exchanges.
83 : * It is unfortunate that this chip doesn't seem to do scatter-gather.
84 : */
85 : bus_dma_tag_t sc_dmat;
86 : bus_dmamap_t sc_ringmap;
87 : bus_dma_segment_t sc_ringseg;
88 :
89 : uint8_t *sc_ring; /* the whole area */
90 : size_t sc_ringsize;
91 :
92 : struct rx_pkt *sc_rxp; /* the part used for RX */
93 : struct tx_pkt_status *sc_txs; /* the parts used for TX */
94 : bus_addr_t sc_txsp;
95 : char *sc_txdbase;
96 : bus_addr_t sc_txdp;
97 :
98 : unsigned int sc_rxcur;
99 : /* the active area is [ack; cur[ */
100 : int sc_txs_cur;
101 : int sc_txs_ack;
102 : int sc_txd_cur;
103 : int sc_txd_ack;
104 : int sc_free_tx_slots;
105 :
106 : void *sc_ih;
107 :
108 : struct arpcom sc_ac;
109 : struct mii_data sc_mii;
110 : struct timeout sc_tick;
111 :
112 : int (*sc_memread)(struct lii_softc *, uint32_t,
113 : uint32_t *);
114 : };
115 :
116 : #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
117 :
118 : int lii_match(struct device *, void *, void *);
119 : void lii_attach(struct device *, struct device *, void *);
120 : int lii_activate(struct device *, int);
121 :
122 : struct cfdriver lii_cd = {
123 : 0,
124 : "lii",
125 : DV_IFNET
126 : };
127 :
128 : struct cfattach lii_ca = {
129 : sizeof(struct lii_softc),
130 : lii_match,
131 : lii_attach,
132 : NULL,
133 : lii_activate
134 : };
135 :
136 : int lii_reset(struct lii_softc *);
137 : int lii_eeprom_present(struct lii_softc *);
138 : void lii_read_macaddr(struct lii_softc *, uint8_t *);
139 : int lii_eeprom_read(struct lii_softc *, uint32_t, uint32_t *);
140 : void lii_spi_configure(struct lii_softc *);
141 : int lii_spi_read(struct lii_softc *, uint32_t, uint32_t *);
142 : void lii_iff(struct lii_softc *);
143 : void lii_tick(void *);
144 :
145 : int lii_alloc_rings(struct lii_softc *);
146 : int lii_free_tx_space(struct lii_softc *);
147 : void lii_tx_put(struct lii_softc *, struct mbuf *);
148 :
149 : int lii_mii_readreg(struct device *, int, int);
150 : void lii_mii_writereg(struct device *, int, int, int);
151 : void lii_mii_statchg(struct device *);
152 :
153 : int lii_media_change(struct ifnet *);
154 : void lii_media_status(struct ifnet *, struct ifmediareq *);
155 :
156 : int lii_init(struct ifnet *);
157 : void lii_start(struct ifnet *);
158 : void lii_stop(struct ifnet *);
159 : void lii_watchdog(struct ifnet *);
160 : int lii_ioctl(struct ifnet *, u_long, caddr_t);
161 :
162 : int lii_intr(void *);
163 : void lii_rxintr(struct lii_softc *);
164 : void lii_txintr(struct lii_softc *);
165 :
166 : const struct pci_matchid lii_devices[] = {
167 : { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2 }
168 : };
169 :
170 : #define LII_READ_4(sc,reg) \
171 : bus_space_read_4((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
172 : #define LII_READ_2(sc,reg) \
173 : bus_space_read_2((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
174 : #define LII_READ_1(sc,reg) \
175 : bus_space_read_1((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
176 : #define LII_WRITE_4(sc,reg,val) \
177 : bus_space_write_4((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
178 : #define LII_WRITE_2(sc,reg,val) \
179 : bus_space_write_2((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
180 : #define LII_WRITE_1(sc,reg,val) \
181 : bus_space_write_1((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
182 :
183 : /*
184 : * Those are the default Linux parameters.
185 : */
186 :
187 : #define AT_TXD_NUM 64
188 : #define AT_TXD_BUFFER_SIZE 8192
189 : #define AT_RXD_NUM 64
190 :
191 : /* Pad the RXD buffer so that the packets are on a 128-byte boundary. */
192 : #define AT_RXD_PADDING 120
193 :
194 : int
195 0 : lii_match(struct device *parent, void *match, void *aux)
196 : {
197 0 : return (pci_matchbyid((struct pci_attach_args *)aux, lii_devices,
198 : nitems(lii_devices)));
199 : }
200 :
201 : void
202 0 : lii_attach(struct device *parent, struct device *self, void *aux)
203 : {
204 0 : struct lii_softc *sc = (struct lii_softc *)self;
205 0 : struct pci_attach_args *pa = aux;
206 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
207 0 : pci_intr_handle_t ih;
208 : pcireg_t memtype;
209 :
210 0 : sc->sc_pc = pa->pa_pc;
211 0 : sc->sc_tag = pa->pa_tag;
212 0 : sc->sc_dmat = pa->pa_dmat;
213 :
214 0 : memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, PCI_MAPREG_START);
215 0 : if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_mmiot,
216 0 : &sc->sc_mmioh, NULL, &sc->sc_mmios, 0)) {
217 0 : printf(": can't map mem space\n");
218 0 : return;
219 : }
220 :
221 0 : if (lii_reset(sc))
222 : goto unmap;
223 :
224 0 : lii_spi_configure(sc);
225 :
226 0 : if (lii_eeprom_present(sc))
227 0 : sc->sc_memread = lii_eeprom_read;
228 : else
229 0 : sc->sc_memread = lii_spi_read;
230 :
231 0 : lii_read_macaddr(sc, sc->sc_ac.ac_enaddr);
232 :
233 0 : if (pci_intr_map(pa, &ih) != 0) {
234 0 : printf(": can't map interrupt\n");
235 0 : goto unmap;
236 : }
237 0 : sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET,
238 0 : lii_intr, sc, DEVNAME(sc));
239 0 : if (sc->sc_ih == NULL) {
240 0 : printf(": can't establish interrupt\n");
241 0 : goto unmap;
242 : }
243 :
244 0 : if (lii_alloc_rings(sc))
245 : goto deintr;
246 :
247 0 : printf(": %s, address %s\n", pci_intr_string(sc->sc_pc, ih),
248 0 : ether_sprintf(sc->sc_ac.ac_enaddr));
249 :
250 0 : timeout_set(&sc->sc_tick, lii_tick, sc);
251 :
252 0 : sc->sc_mii.mii_ifp = ifp;
253 0 : sc->sc_mii.mii_readreg = lii_mii_readreg;
254 0 : sc->sc_mii.mii_writereg = lii_mii_writereg;
255 0 : sc->sc_mii.mii_statchg = lii_mii_statchg;
256 0 : ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, lii_media_change,
257 : lii_media_status);
258 0 : mii_attach(self, &sc->sc_mii, 0xffffffff, 1,
259 : MII_OFFSET_ANY, 0);
260 0 : ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
261 :
262 0 : strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
263 0 : ifp->if_softc = sc;
264 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
265 0 : ifp->if_capabilities = IFCAP_VLAN_MTU;
266 0 : ifp->if_ioctl = lii_ioctl;
267 0 : ifp->if_start = lii_start;
268 0 : ifp->if_watchdog = lii_watchdog;
269 :
270 0 : if_attach(ifp);
271 0 : ether_ifattach(ifp);
272 :
273 0 : return;
274 :
275 : deintr:
276 0 : pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
277 : unmap:
278 0 : bus_space_unmap(sc->sc_mmiot, sc->sc_mmioh, sc->sc_mmios);
279 0 : return;
280 0 : }
281 :
282 : int
283 0 : lii_activate(struct device *self, int act)
284 : {
285 0 : struct lii_softc *sc = (struct lii_softc *)self;
286 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
287 : int rv = 0;
288 :
289 0 : switch (act) {
290 : case DVACT_SUSPEND:
291 0 : if (ifp->if_flags & IFF_RUNNING)
292 0 : lii_stop(ifp);
293 0 : rv = config_activate_children(self, act);
294 0 : break;
295 : case DVACT_RESUME:
296 0 : if (ifp->if_flags & IFF_UP)
297 0 : lii_init(ifp);
298 : break;
299 : default:
300 0 : rv = config_activate_children(self, act);
301 0 : break;
302 : }
303 0 : return (rv);
304 : }
305 :
306 : int
307 0 : lii_reset(struct lii_softc *sc)
308 : {
309 : int i;
310 :
311 : DPRINTF(("lii_reset\n"));
312 :
313 0 : LII_WRITE_4(sc, LII_SMC, SMC_SOFT_RST);
314 0 : DELAY(1000);
315 :
316 0 : for (i = 0; i < 10; ++i) {
317 0 : if (LII_READ_4(sc, LII_BIS) == 0)
318 : break;
319 0 : DELAY(1000);
320 : }
321 :
322 0 : if (i == 10) {
323 0 : printf("%s: reset failed\n", DEVNAME(sc));
324 0 : return 1;
325 : }
326 :
327 0 : LII_WRITE_4(sc, LII_PHYC, PHYC_ENABLE);
328 0 : DELAY(10);
329 :
330 : /* Init PCI-Express module */
331 : /* Magic Numbers Warning */
332 0 : LII_WRITE_4(sc, 0x12fc, 0x00006500);
333 0 : LII_WRITE_4(sc, 0x1008, 0x00008000 |
334 : LII_READ_4(sc, 0x1008));
335 :
336 0 : return 0;
337 0 : }
338 :
339 : int
340 0 : lii_eeprom_present(struct lii_softc *sc)
341 : {
342 : uint32_t val;
343 :
344 0 : val = LII_READ_4(sc, LII_SFC);
345 0 : if (val & SFC_EN_VPD)
346 0 : LII_WRITE_4(sc, LII_SFC, val & ~(SFC_EN_VPD));
347 :
348 0 : return pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_VPD,
349 0 : NULL, NULL) == 1;
350 : }
351 :
352 : int
353 0 : lii_eeprom_read(struct lii_softc *sc, uint32_t reg, uint32_t *val)
354 : {
355 0 : return pci_vpd_read(sc->sc_pc, sc->sc_tag, reg, 1, (pcireg_t *)val);
356 : }
357 :
358 : void
359 0 : lii_spi_configure(struct lii_softc *sc)
360 : {
361 : /*
362 : * We don't offer a way to configure the SPI Flash vendor parameter, so
363 : * the table is given for reference
364 : */
365 : static const struct lii_spi_flash_vendor {
366 : const char *sfv_name;
367 : const uint8_t sfv_opcodes[9];
368 : } lii_sfv[] = {
369 : { "Atmel", { 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 } },
370 : { "SST", { 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 } },
371 : { "ST", { 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xab, 0xd8, 0xc7 } },
372 : };
373 : #define SF_OPCODE_WRSR 0
374 : #define SF_OPCODE_READ 1
375 : #define SF_OPCODE_PRGM 2
376 : #define SF_OPCODE_WREN 3
377 : #define SF_OPCODE_WRDI 4
378 : #define SF_OPCODE_RDSR 5
379 : #define SF_OPCODE_RDID 6
380 : #define SF_OPCODE_SECT_ER 7
381 : #define SF_OPCODE_CHIP_ER 8
382 :
383 : #define SF_DEFAULT_VENDOR 0
384 : static const uint8_t vendor = SF_DEFAULT_VENDOR;
385 :
386 : /*
387 : * Why isn't WRDI used? Heck if I know.
388 : */
389 :
390 0 : LII_WRITE_1(sc, LII_SFOP_WRSR,
391 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_WRSR]);
392 0 : LII_WRITE_1(sc, LII_SFOP_READ,
393 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_READ]);
394 0 : LII_WRITE_1(sc, LII_SFOP_PROGRAM,
395 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_PRGM]);
396 0 : LII_WRITE_1(sc, LII_SFOP_WREN,
397 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_WREN]);
398 0 : LII_WRITE_1(sc, LII_SFOP_RDSR,
399 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_RDSR]);
400 0 : LII_WRITE_1(sc, LII_SFOP_RDID,
401 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_RDID]);
402 0 : LII_WRITE_1(sc, LII_SFOP_SC_ERASE,
403 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_SECT_ER]);
404 0 : LII_WRITE_1(sc, LII_SFOP_CHIP_ERASE,
405 : lii_sfv[vendor].sfv_opcodes[SF_OPCODE_CHIP_ER]);
406 0 : }
407 :
408 : #define MAKE_SFC(cssetup, clkhi, clklo, cshold, cshi, ins) \
409 : ( (((cssetup) & SFC_CS_SETUP_MASK) \
410 : << SFC_CS_SETUP_SHIFT) \
411 : | (((clkhi) & SFC_CLK_HI_MASK) \
412 : << SFC_CLK_HI_SHIFT) \
413 : | (((clklo) & SFC_CLK_LO_MASK) \
414 : << SFC_CLK_LO_SHIFT) \
415 : | (((cshold) & SFC_CS_HOLD_MASK) \
416 : << SFC_CS_HOLD_SHIFT) \
417 : | (((cshi) & SFC_CS_HI_MASK) \
418 : << SFC_CS_HI_SHIFT) \
419 : | (((ins) & SFC_INS_MASK) \
420 : << SFC_INS_SHIFT))
421 :
422 : #define CUSTOM_SPI_CS_SETUP 2
423 : #define CUSTOM_SPI_CLK_HI 2
424 : #define CUSTOM_SPI_CLK_LO 2
425 : #define CUSTOM_SPI_CS_HOLD 2
426 : #define CUSTOM_SPI_CS_HI 3
427 :
428 : int
429 0 : lii_spi_read(struct lii_softc *sc, uint32_t reg, uint32_t *val)
430 : {
431 : uint32_t v;
432 : int i;
433 :
434 0 : LII_WRITE_4(sc, LII_SF_DATA, 0);
435 0 : LII_WRITE_4(sc, LII_SF_ADDR, reg);
436 :
437 : v = SFC_WAIT_READY |
438 : MAKE_SFC(CUSTOM_SPI_CS_SETUP, CUSTOM_SPI_CLK_HI,
439 : CUSTOM_SPI_CLK_LO, CUSTOM_SPI_CS_HOLD, CUSTOM_SPI_CS_HI, 1);
440 :
441 0 : LII_WRITE_4(sc, LII_SFC, v);
442 : v |= SFC_START;
443 0 : LII_WRITE_4(sc, LII_SFC, v);
444 :
445 0 : for (i = 0; i < 10; ++i) {
446 0 : DELAY(1000);
447 0 : if (!(LII_READ_4(sc, LII_SFC) & SFC_START))
448 : break;
449 : }
450 0 : if (i == 10)
451 0 : return EBUSY;
452 :
453 0 : *val = LII_READ_4(sc, LII_SF_DATA);
454 0 : return 0;
455 0 : }
456 :
457 : void
458 0 : lii_read_macaddr(struct lii_softc *sc, uint8_t *ea)
459 : {
460 : uint32_t offset = 0x100;
461 0 : uint32_t val, val1, addr0 = 0, addr1 = 0;
462 : uint8_t found = 0;
463 :
464 0 : while ((*sc->sc_memread)(sc, offset, &val) == 0) {
465 0 : offset += 4;
466 :
467 : /* Each chunk of data starts with a signature */
468 0 : if ((val & 0xff) != 0x5a)
469 : break;
470 0 : if ((*sc->sc_memread)(sc, offset, &val1))
471 : break;
472 :
473 0 : offset += 4;
474 :
475 0 : val >>= 16;
476 0 : switch (val) {
477 : case LII_MAC_ADDR_0:
478 0 : addr0 = val1;
479 0 : ++found;
480 0 : break;
481 : case LII_MAC_ADDR_1:
482 0 : addr1 = val1;
483 0 : ++found;
484 0 : break;
485 : default:
486 0 : continue;
487 : }
488 : }
489 :
490 : #ifdef LII_DEBUG
491 : if (found < 2)
492 : printf(": error reading MAC address, using registers...\n");
493 : #endif
494 :
495 : addr0 = htole32(addr0);
496 : addr1 = htole32(addr1);
497 :
498 0 : if ((addr0 == 0xffffff && (addr1 & 0xffff) == 0xffff) ||
499 0 : (addr0 == 0 && (addr1 & 0xffff) == 0)) {
500 0 : addr0 = htole32(LII_READ_4(sc, LII_MAC_ADDR_0));
501 0 : addr1 = htole32(LII_READ_4(sc, LII_MAC_ADDR_1));
502 0 : }
503 :
504 0 : ea[0] = (addr1 & 0x0000ff00) >> 8;
505 0 : ea[1] = (addr1 & 0x000000ff);
506 0 : ea[2] = (addr0 & 0xff000000) >> 24;
507 0 : ea[3] = (addr0 & 0x00ff0000) >> 16;
508 0 : ea[4] = (addr0 & 0x0000ff00) >> 8;
509 0 : ea[5] = (addr0 & 0x000000ff);
510 0 : }
511 :
512 : int
513 0 : lii_mii_readreg(struct device *dev, int phy, int reg)
514 : {
515 0 : struct lii_softc *sc = (struct lii_softc *)dev;
516 : uint32_t val;
517 : int i;
518 :
519 0 : val = (reg & MDIOC_REG_MASK) << MDIOC_REG_SHIFT;
520 :
521 0 : val |= MDIOC_START | MDIOC_SUP_PREAMBLE;
522 : val |= MDIOC_CLK_25_4 << MDIOC_CLK_SEL_SHIFT;
523 :
524 0 : val |= MDIOC_READ;
525 :
526 0 : LII_WRITE_4(sc, LII_MDIOC, val);
527 :
528 0 : for (i = 0; i < MDIO_WAIT_TIMES; ++i) {
529 0 : DELAY(2);
530 0 : val = LII_READ_4(sc, LII_MDIOC);
531 0 : if ((val & (MDIOC_START | MDIOC_BUSY)) == 0)
532 : break;
533 : }
534 :
535 0 : if (i == MDIO_WAIT_TIMES) {
536 0 : printf("%s: timeout reading PHY %d reg %d\n", DEVNAME(sc), phy,
537 : reg);
538 0 : }
539 :
540 0 : return (val & 0x0000ffff);
541 : }
542 :
543 : void
544 0 : lii_mii_writereg(struct device *dev, int phy, int reg, int data)
545 : {
546 0 : struct lii_softc *sc = (struct lii_softc *)dev;
547 : uint32_t val;
548 : int i;
549 :
550 0 : val = (reg & MDIOC_REG_MASK) << MDIOC_REG_SHIFT;
551 0 : val |= (data & MDIOC_DATA_MASK) << MDIOC_DATA_SHIFT;
552 :
553 0 : val |= MDIOC_START | MDIOC_SUP_PREAMBLE;
554 : val |= MDIOC_CLK_25_4 << MDIOC_CLK_SEL_SHIFT;
555 :
556 : /* val |= MDIOC_WRITE; */
557 :
558 0 : LII_WRITE_4(sc, LII_MDIOC, val);
559 :
560 0 : for (i = 0; i < MDIO_WAIT_TIMES; ++i) {
561 0 : DELAY(2);
562 0 : val = LII_READ_4(sc, LII_MDIOC);
563 0 : if ((val & (MDIOC_START | MDIOC_BUSY)) == 0)
564 : break;
565 : }
566 :
567 0 : if (i == MDIO_WAIT_TIMES) {
568 0 : printf("%s: timeout writing PHY %d reg %d\n", DEVNAME(sc), phy,
569 : reg);
570 0 : }
571 0 : }
572 :
573 : void
574 0 : lii_mii_statchg(struct device *dev)
575 : {
576 0 : struct lii_softc *sc = (struct lii_softc *)dev;
577 : uint32_t val;
578 :
579 : DPRINTF(("lii_mii_statchg\n"));
580 :
581 0 : val = LII_READ_4(sc, LII_MACC);
582 :
583 0 : if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
584 0 : val |= MACC_FDX;
585 : else
586 0 : val &= ~MACC_FDX;
587 :
588 0 : LII_WRITE_4(sc, LII_MACC, val);
589 0 : }
590 :
591 : int
592 0 : lii_media_change(struct ifnet *ifp)
593 : {
594 0 : struct lii_softc *sc = ifp->if_softc;
595 :
596 : DPRINTF(("lii_media_change\n"));
597 :
598 0 : if (ifp->if_flags & IFF_UP)
599 0 : mii_mediachg(&sc->sc_mii);
600 0 : return 0;
601 : }
602 :
603 : void
604 0 : lii_media_status(struct ifnet *ifp, struct ifmediareq *imr)
605 : {
606 0 : struct lii_softc *sc = ifp->if_softc;
607 :
608 : DPRINTF(("lii_media_status\n"));
609 :
610 0 : mii_pollstat(&sc->sc_mii);
611 0 : imr->ifm_status = sc->sc_mii.mii_media_status;
612 0 : imr->ifm_active = sc->sc_mii.mii_media_active;
613 0 : }
614 :
615 : int
616 0 : lii_init(struct ifnet *ifp)
617 : {
618 0 : struct lii_softc *sc = ifp->if_softc;
619 : uint32_t val;
620 : int error;
621 :
622 : DPRINTF(("lii_init\n"));
623 :
624 0 : lii_stop(ifp);
625 :
626 0 : memset(sc->sc_ring, 0, sc->sc_ringsize);
627 :
628 : /* Disable all interrupts */
629 0 : LII_WRITE_4(sc, LII_ISR, 0xffffffff);
630 :
631 0 : LII_WRITE_4(sc, LII_DESC_BASE_ADDR_HI, 0);
632 : /* XXX
633 : sc->sc_ringmap->dm_segs[0].ds_addr >> 32);
634 : */
635 0 : LII_WRITE_4(sc, LII_RXD_BASE_ADDR_LO,
636 : (sc->sc_ringmap->dm_segs[0].ds_addr & 0xffffffff)
637 : + AT_RXD_PADDING);
638 0 : LII_WRITE_4(sc, LII_TXS_BASE_ADDR_LO,
639 : sc->sc_txsp & 0xffffffff);
640 0 : LII_WRITE_4(sc, LII_TXD_BASE_ADDR_LO,
641 : sc->sc_txdp & 0xffffffff);
642 :
643 0 : LII_WRITE_2(sc, LII_TXD_BUFFER_SIZE, AT_TXD_BUFFER_SIZE / 4);
644 0 : LII_WRITE_2(sc, LII_TXS_NUM_ENTRIES, AT_TXD_NUM);
645 0 : LII_WRITE_2(sc, LII_RXD_NUM_ENTRIES, AT_RXD_NUM);
646 :
647 : /*
648 : * Inter Paket Gap Time = 0x60 (IPGT)
649 : * Minimum inter-frame gap for RX = 0x50 (MIFG)
650 : * 64-bit Carrier-Sense window = 0x40 (IPGR1)
651 : * 96-bit IPG window = 0x60 (IPGR2)
652 : */
653 0 : LII_WRITE_4(sc, LII_MIPFG, 0x60405060);
654 :
655 : /*
656 : * Collision window = 0x37 (LCOL)
657 : * Maximum # of retrans = 0xf (RETRY)
658 : * Maximum binary expansion # = 0xa (ABEBT)
659 : * IPG to start jam = 0x7 (JAMIPG)
660 : */
661 0 : LII_WRITE_4(sc, LII_MHDC, 0x07a0f037 |
662 : MHDC_EXC_DEF_EN);
663 :
664 : /* 100 means 200us */
665 0 : LII_WRITE_2(sc, LII_IMTIV, 100);
666 0 : LII_WRITE_2(sc, LII_SMC, SMC_ITIMER_EN);
667 :
668 : /* 500000 means 100ms */
669 0 : LII_WRITE_2(sc, LII_IALTIV, 50000);
670 :
671 0 : LII_WRITE_4(sc, LII_MTU, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
672 :
673 : /* unit unknown for TX cur-through threshold */
674 0 : LII_WRITE_4(sc, LII_TX_CUT_THRESH, 0x177);
675 :
676 0 : LII_WRITE_2(sc, LII_PAUSE_ON_TH, AT_RXD_NUM * 7 / 8);
677 0 : LII_WRITE_2(sc, LII_PAUSE_OFF_TH, AT_RXD_NUM / 12);
678 :
679 0 : sc->sc_rxcur = 0;
680 0 : sc->sc_txs_cur = sc->sc_txs_ack = 0;
681 0 : sc->sc_txd_cur = sc->sc_txd_ack = 0;
682 0 : sc->sc_free_tx_slots = 1;
683 0 : LII_WRITE_2(sc, LII_MB_TXD_WR_IDX, sc->sc_txd_cur);
684 0 : LII_WRITE_2(sc, LII_MB_RXD_RD_IDX, sc->sc_rxcur);
685 :
686 0 : LII_WRITE_1(sc, LII_DMAR, DMAR_EN);
687 0 : LII_WRITE_1(sc, LII_DMAW, DMAW_EN);
688 :
689 0 : LII_WRITE_4(sc, LII_SMC, LII_READ_4(sc, LII_SMC) | SMC_MANUAL_INT);
690 :
691 0 : error = ((LII_READ_4(sc, LII_ISR) & ISR_PHY_LINKDOWN) != 0);
692 0 : LII_WRITE_4(sc, LII_ISR, 0x3fffffff);
693 0 : LII_WRITE_4(sc, LII_ISR, 0);
694 0 : if (error) {
695 0 : printf("%s: init failed\n", DEVNAME(sc));
696 0 : goto out;
697 : }
698 :
699 : /*
700 : * Initialise MAC.
701 : */
702 0 : val = LII_READ_4(sc, LII_MACC) & MACC_FDX;
703 :
704 0 : val |= MACC_RX_EN | MACC_TX_EN | MACC_MACLP_CLK_PHY |
705 : MACC_TX_FLOW_EN | MACC_RX_FLOW_EN | MACC_ADD_CRC |
706 : MACC_PAD;
707 :
708 0 : val |= 7 << MACC_PREAMBLE_LEN_SHIFT;
709 0 : val |= 2 << MACC_HDX_LEFT_BUF_SHIFT;
710 :
711 0 : LII_WRITE_4(sc, LII_MACC, val);
712 :
713 : /* Set the hardware MAC address. */
714 0 : LII_WRITE_4(sc, LII_MAC_ADDR_0, letoh32((sc->sc_ac.ac_enaddr[2] << 24) |
715 : (sc->sc_ac.ac_enaddr[3] << 16) | (sc->sc_ac.ac_enaddr[4] << 8) |
716 : sc->sc_ac.ac_enaddr[5]));
717 0 : LII_WRITE_4(sc, LII_MAC_ADDR_1,
718 : letoh32((sc->sc_ac.ac_enaddr[0] << 8) | sc->sc_ac.ac_enaddr[1]));
719 :
720 : /* Program promiscuous mode and multicast filters. */
721 0 : lii_iff(sc);
722 :
723 0 : mii_mediachg(&sc->sc_mii);
724 :
725 0 : LII_WRITE_4(sc, LII_IMR, IMR_NORMAL_MASK);
726 :
727 0 : timeout_add_sec(&sc->sc_tick, 1);
728 :
729 0 : ifp->if_flags |= IFF_RUNNING;
730 0 : ifq_clr_oactive(&ifp->if_snd);
731 :
732 : out:
733 0 : return error;
734 : }
735 :
736 : void
737 0 : lii_tx_put(struct lii_softc *sc, struct mbuf *m)
738 : {
739 : int left;
740 : struct tx_pkt_header *tph =
741 0 : (struct tx_pkt_header *)(sc->sc_txdbase + sc->sc_txd_cur);
742 :
743 0 : memset(tph, 0, sizeof *tph);
744 0 : tph->txph_size = m->m_pkthdr.len;
745 :
746 0 : sc->sc_txd_cur = (sc->sc_txd_cur + 4) % AT_TXD_BUFFER_SIZE;
747 :
748 : /*
749 : * We already know we have enough space, so if there is a part of the
750 : * space ahead of txd_cur that is active, it doesn't matter because
751 : * left will be large enough even without it.
752 : */
753 0 : left = AT_TXD_BUFFER_SIZE - sc->sc_txd_cur;
754 :
755 0 : if (left > m->m_pkthdr.len) {
756 0 : m_copydata(m, 0, m->m_pkthdr.len,
757 0 : sc->sc_txdbase + sc->sc_txd_cur);
758 0 : sc->sc_txd_cur += m->m_pkthdr.len;
759 0 : } else {
760 0 : m_copydata(m, 0, left, sc->sc_txdbase + sc->sc_txd_cur);
761 0 : m_copydata(m, left, m->m_pkthdr.len - left, sc->sc_txdbase);
762 0 : sc->sc_txd_cur = m->m_pkthdr.len - left;
763 : }
764 :
765 : /* Round to a 32-bit boundary */
766 0 : sc->sc_txd_cur = ((sc->sc_txd_cur + 3) & ~3) % AT_TXD_BUFFER_SIZE;
767 0 : if (sc->sc_txd_cur == sc->sc_txd_ack)
768 0 : sc->sc_free_tx_slots = 0;
769 0 : }
770 :
771 : int
772 0 : lii_free_tx_space(struct lii_softc *sc)
773 : {
774 : int space;
775 :
776 0 : if (sc->sc_txd_cur >= sc->sc_txd_ack)
777 0 : space = (AT_TXD_BUFFER_SIZE - sc->sc_txd_cur) +
778 : sc->sc_txd_ack;
779 : else
780 0 : space = sc->sc_txd_ack - sc->sc_txd_cur;
781 :
782 : /* Account for the tx_pkt_header */
783 0 : return (space - 4);
784 : }
785 :
786 : void
787 0 : lii_start(struct ifnet *ifp)
788 : {
789 0 : struct lii_softc *sc = ifp->if_softc;
790 : struct mbuf *m0;
791 :
792 : DPRINTF(("lii_start\n"));
793 :
794 0 : if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
795 0 : return;
796 :
797 0 : for (;;) {
798 0 : m0 = ifq_deq_begin(&ifp->if_snd);
799 0 : if (m0 == NULL)
800 : break;
801 :
802 0 : if (!sc->sc_free_tx_slots ||
803 0 : lii_free_tx_space(sc) < m0->m_pkthdr.len) {
804 0 : ifq_deq_rollback(&ifp->if_snd, m0);
805 0 : ifq_set_oactive(&ifp->if_snd);
806 0 : break;
807 : }
808 :
809 0 : lii_tx_put(sc, m0);
810 :
811 : DPRINTF(("lii_start: put %d\n", sc->sc_txs_cur));
812 :
813 0 : sc->sc_txs[sc->sc_txs_cur].txps_update = 0;
814 0 : sc->sc_txs_cur = (sc->sc_txs_cur + 1) % AT_TXD_NUM;
815 0 : if (sc->sc_txs_cur == sc->sc_txs_ack)
816 0 : sc->sc_free_tx_slots = 0;
817 :
818 0 : LII_WRITE_2(sc, LII_MB_TXD_WR_IDX, sc->sc_txd_cur/4);
819 :
820 0 : ifq_deq_commit(&ifp->if_snd, m0);
821 :
822 : #if NBPFILTER > 0
823 0 : if (ifp->if_bpf != NULL)
824 0 : bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
825 : #endif
826 0 : m_freem(m0);
827 : }
828 0 : }
829 :
830 : void
831 0 : lii_stop(struct ifnet *ifp)
832 : {
833 0 : struct lii_softc *sc = ifp->if_softc;
834 :
835 0 : timeout_del(&sc->sc_tick);
836 :
837 0 : ifp->if_timer = 0;
838 0 : ifp->if_flags &= ~IFF_RUNNING;
839 0 : ifq_clr_oactive(&ifp->if_snd);
840 :
841 0 : mii_down(&sc->sc_mii);
842 :
843 0 : lii_reset(sc);
844 :
845 0 : LII_WRITE_4(sc, LII_IMR, 0);
846 0 : }
847 :
848 : int
849 0 : lii_intr(void *v)
850 : {
851 0 : struct lii_softc *sc = v;
852 : uint32_t status;
853 :
854 0 : status = LII_READ_4(sc, LII_ISR);
855 0 : if (status == 0)
856 0 : return 0;
857 :
858 : DPRINTF(("lii_intr (%x)\n", status));
859 :
860 : /* Clear the interrupt and disable them */
861 0 : LII_WRITE_4(sc, LII_ISR, status | ISR_DIS_INT);
862 :
863 0 : if (status & (ISR_PHY | ISR_MANUAL)) {
864 : /* Ack PHY interrupt. Magic register */
865 0 : if (status & ISR_PHY)
866 0 : (void)lii_mii_readreg(&sc->sc_dev, 1, 19);
867 0 : mii_mediachg(&sc->sc_mii);
868 0 : }
869 :
870 0 : if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST | ISR_PHY_LINKDOWN)) {
871 0 : lii_init(&sc->sc_ac.ac_if);
872 0 : return 1;
873 : }
874 :
875 0 : if (status & ISR_RX_EVENT) {
876 : #ifdef LII_DEBUG
877 : if (!(status & ISR_RS_UPDATE))
878 : printf("rxintr %08x\n", status);
879 : #endif
880 0 : lii_rxintr(sc);
881 0 : }
882 :
883 0 : if (status & ISR_TX_EVENT)
884 0 : lii_txintr(sc);
885 :
886 : /* Re-enable interrupts */
887 0 : LII_WRITE_4(sc, LII_ISR, 0);
888 :
889 0 : return 1;
890 0 : }
891 :
892 : void
893 0 : lii_rxintr(struct lii_softc *sc)
894 : {
895 0 : struct mbuf_list ml = MBUF_LIST_INITIALIZER();
896 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
897 : struct rx_pkt *rxp;
898 : struct mbuf *m;
899 : uint16_t size;
900 :
901 : DPRINTF(("lii_rxintr\n"));
902 :
903 0 : for (;;) {
904 0 : rxp = &sc->sc_rxp[sc->sc_rxcur];
905 0 : if (rxp->rxp_update == 0)
906 : break;
907 :
908 : DPRINTF(("lii_rxintr: getting %u (%u) [%x]\n", sc->sc_rxcur,
909 : rxp->rxp_size, rxp->rxp_flags));
910 0 : sc->sc_rxcur = (sc->sc_rxcur + 1) % AT_RXD_NUM;
911 0 : rxp->rxp_update = 0;
912 0 : if (!(rxp->rxp_flags & LII_RXF_SUCCESS)) {
913 0 : ++ifp->if_ierrors;
914 0 : continue;
915 : }
916 :
917 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
918 0 : if (m == NULL) {
919 0 : ++ifp->if_ierrors;
920 0 : continue;
921 : }
922 0 : size = rxp->rxp_size - ETHER_CRC_LEN;
923 0 : if (size > MHLEN) {
924 0 : MCLGET(m, M_DONTWAIT);
925 0 : if ((m->m_flags & M_EXT) == 0) {
926 0 : m_freem(m);
927 0 : ++ifp->if_ierrors;
928 0 : continue;
929 : }
930 : }
931 :
932 : /* Copy the packet withhout the FCS */
933 0 : m->m_pkthdr.len = m->m_len = size;
934 0 : memcpy(mtod(m, void *), &rxp->rxp_data[0], size);
935 :
936 0 : ml_enqueue(&ml, m);
937 : }
938 :
939 0 : if_input(ifp, &ml);
940 :
941 0 : LII_WRITE_4(sc, LII_MB_RXD_RD_IDX, sc->sc_rxcur);
942 0 : }
943 :
944 : void
945 0 : lii_txintr(struct lii_softc *sc)
946 : {
947 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
948 : struct tx_pkt_status *txs;
949 : struct tx_pkt_header *txph;
950 :
951 : DPRINTF(("lii_txintr\n"));
952 :
953 0 : for (;;) {
954 0 : txs = &sc->sc_txs[sc->sc_txs_ack];
955 0 : if (txs->txps_update == 0)
956 : break;
957 : DPRINTF(("lii_txintr: ack'd %d\n", sc->sc_txs_ack));
958 0 : sc->sc_txs_ack = (sc->sc_txs_ack + 1) % AT_TXD_NUM;
959 0 : sc->sc_free_tx_slots = 1;
960 :
961 0 : txs->txps_update = 0;
962 :
963 0 : txph = (struct tx_pkt_header *)
964 0 : (sc->sc_txdbase + sc->sc_txd_ack);
965 :
966 0 : if (txph->txph_size != txs->txps_size) {
967 0 : printf("%s: mismatched status and packet\n",
968 0 : DEVNAME(sc));
969 0 : }
970 :
971 : /*
972 : * Move ack by the packet size, taking the packet header in
973 : * account and round to the next 32-bit boundary
974 : * (7 = sizeof(header) + 3)
975 : */
976 0 : sc->sc_txd_ack = (sc->sc_txd_ack + txph->txph_size + 7 ) & ~3;
977 0 : sc->sc_txd_ack %= AT_TXD_BUFFER_SIZE;
978 :
979 0 : if (!ISSET(txs->txps_flags, LII_TXF_SUCCESS))
980 0 : ++ifp->if_oerrors;
981 0 : ifq_clr_oactive(&ifp->if_snd);
982 : }
983 :
984 0 : if (sc->sc_free_tx_slots)
985 0 : lii_start(ifp);
986 0 : }
987 :
988 : int
989 0 : lii_alloc_rings(struct lii_softc *sc)
990 : {
991 0 : int nsegs;
992 : bus_size_t bs;
993 :
994 : /*
995 : * We need a big chunk of DMA-friendly memory because descriptors
996 : * are not separate from data on that crappy hardware, which means
997 : * we'll have to copy data from and to that memory zone to and from
998 : * the mbufs.
999 : *
1000 : * How lame is that? Using the default values from the Linux driver,
1001 : * we allocate space for receiving up to 64 full-size Ethernet frames,
1002 : * and only 8kb for transmitting up to 64 Ethernet frames.
1003 : */
1004 :
1005 0 : sc->sc_ringsize = bs = AT_RXD_PADDING
1006 : + AT_RXD_NUM * sizeof(struct rx_pkt)
1007 : + AT_TXD_NUM * sizeof(struct tx_pkt_status)
1008 : + AT_TXD_BUFFER_SIZE;
1009 :
1010 0 : if (bus_dmamap_create(sc->sc_dmat, bs, 1, bs, (1<<30),
1011 0 : BUS_DMA_NOWAIT, &sc->sc_ringmap) != 0) {
1012 0 : printf(": failed to create DMA map\n");
1013 0 : return 1;
1014 : }
1015 :
1016 0 : if (bus_dmamem_alloc(sc->sc_dmat, bs, PAGE_SIZE, (1<<30),
1017 0 : &sc->sc_ringseg, 1, &nsegs, BUS_DMA_NOWAIT) != 0) {
1018 0 : printf(": failed to allocate DMA memory\n");
1019 0 : goto destroy;
1020 : }
1021 :
1022 0 : if (bus_dmamem_map(sc->sc_dmat, &sc->sc_ringseg, nsegs, bs,
1023 0 : (caddr_t *)&sc->sc_ring, BUS_DMA_NOWAIT) != 0) {
1024 0 : printf(": failed to map DMA memory\n");
1025 0 : goto free;
1026 : }
1027 :
1028 0 : if (bus_dmamap_load(sc->sc_dmat, sc->sc_ringmap, sc->sc_ring,
1029 0 : bs, NULL, BUS_DMA_NOWAIT) != 0) {
1030 0 : printf(": failed to load DMA memory\n");
1031 : goto unmap;
1032 : }
1033 :
1034 0 : sc->sc_rxp = (void *)(sc->sc_ring + AT_RXD_PADDING);
1035 0 : sc->sc_txs = (void *)(sc->sc_ring + AT_RXD_PADDING
1036 0 : + AT_RXD_NUM * sizeof(struct rx_pkt));
1037 0 : sc->sc_txdbase = ((char *)sc->sc_txs)
1038 0 : + AT_TXD_NUM * sizeof(struct tx_pkt_status);
1039 0 : sc->sc_txsp = sc->sc_ringmap->dm_segs[0].ds_addr
1040 0 : + ((char *)sc->sc_txs - (char *)sc->sc_ring);
1041 0 : sc->sc_txdp = sc->sc_ringmap->dm_segs[0].ds_addr
1042 0 : + ((char *)sc->sc_txdbase - (char *)sc->sc_ring);
1043 :
1044 0 : return 0;
1045 :
1046 : unmap:
1047 0 : bus_dmamem_unmap(sc->sc_dmat, sc->sc_ring, bs);
1048 : free:
1049 0 : bus_dmamem_free(sc->sc_dmat, &sc->sc_ringseg, nsegs);
1050 : destroy:
1051 0 : bus_dmamap_destroy(sc->sc_dmat, sc->sc_ringmap);
1052 0 : return 1;
1053 0 : }
1054 :
1055 : void
1056 0 : lii_watchdog(struct ifnet *ifp)
1057 : {
1058 0 : struct lii_softc *sc = ifp->if_softc;
1059 :
1060 0 : printf("%s: watchdog timeout\n", DEVNAME(sc));
1061 0 : ++ifp->if_oerrors;
1062 0 : lii_init(ifp);
1063 0 : }
1064 :
1065 : int
1066 0 : lii_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
1067 : {
1068 0 : struct lii_softc *sc = ifp->if_softc;
1069 0 : struct ifreq *ifr = (struct ifreq *)addr;
1070 : int s, error = 0;
1071 :
1072 0 : s = splnet();
1073 :
1074 0 : switch(cmd) {
1075 : case SIOCSIFADDR:
1076 0 : SET(ifp->if_flags, IFF_UP);
1077 : /* FALLTHROUGH */
1078 :
1079 : case SIOCSIFFLAGS:
1080 0 : if (ISSET(ifp->if_flags, IFF_UP)) {
1081 0 : if (ISSET(ifp->if_flags, IFF_RUNNING))
1082 0 : error = ENETRESET;
1083 : else
1084 0 : lii_init(ifp);
1085 : } else {
1086 0 : if (ISSET(ifp->if_flags, IFF_RUNNING))
1087 0 : lii_stop(ifp);
1088 : }
1089 : break;
1090 :
1091 : case SIOCSIFMEDIA:
1092 : case SIOCGIFMEDIA:
1093 0 : error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1094 0 : break;
1095 :
1096 : default:
1097 0 : error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
1098 0 : }
1099 :
1100 0 : if (error == ENETRESET) {
1101 0 : if (ifp->if_flags & IFF_RUNNING)
1102 0 : lii_iff(sc);
1103 : error = 0;
1104 0 : }
1105 :
1106 0 : splx(s);
1107 0 : return error;
1108 : }
1109 :
1110 : void
1111 0 : lii_iff(struct lii_softc *sc)
1112 : {
1113 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
1114 : struct arpcom *ac = &sc->sc_ac;
1115 : struct ether_multi *enm;
1116 : struct ether_multistep step;
1117 0 : uint32_t hashes[2];
1118 : uint32_t crc, val;
1119 :
1120 0 : val = LII_READ_4(sc, LII_MACC);
1121 0 : val &= ~(MACC_ALLMULTI_EN | MACC_BCAST_EN | MACC_PROMISC_EN);
1122 0 : ifp->if_flags &= ~IFF_ALLMULTI;
1123 :
1124 : /*
1125 : * Always accept broadcast frames.
1126 : */
1127 0 : val |= MACC_BCAST_EN;
1128 :
1129 0 : if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
1130 0 : ifp->if_flags |= IFF_ALLMULTI;
1131 0 : if (ifp->if_flags & IFF_PROMISC)
1132 0 : val |= MACC_PROMISC_EN;
1133 : else
1134 0 : val |= MACC_ALLMULTI_EN;
1135 0 : hashes[0] = hashes[1] = 0xFFFFFFFF;
1136 0 : } else {
1137 : /* Program new filter. */
1138 0 : bzero(hashes, sizeof(hashes));
1139 :
1140 0 : ETHER_FIRST_MULTI(step, ac, enm);
1141 0 : while (enm != NULL) {
1142 0 : crc = ether_crc32_be(enm->enm_addrlo,
1143 : ETHER_ADDR_LEN);
1144 :
1145 0 : hashes[((crc >> 31) & 0x1)] |=
1146 0 : (1 << ((crc >> 26) & 0x1f));
1147 :
1148 0 : ETHER_NEXT_MULTI(step, enm);
1149 : }
1150 : }
1151 :
1152 0 : LII_WRITE_4(sc, LII_MHT, hashes[0]);
1153 0 : LII_WRITE_4(sc, LII_MHT + 4, hashes[1]);
1154 0 : LII_WRITE_4(sc, LII_MACC, val);
1155 0 : }
1156 :
1157 : void
1158 0 : lii_tick(void *v)
1159 : {
1160 0 : struct lii_softc *sc = v;
1161 : int s;
1162 :
1163 0 : s = splnet();
1164 0 : mii_tick(&sc->sc_mii);
1165 0 : splx(s);
1166 :
1167 0 : timeout_add_sec(&sc->sc_tick, 1);
1168 0 : }
|