| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_cas.c,v 1.26 2016/12/15 09:28:05 ozaki-r Exp $ */ | | 1 | /* $NetBSD: if_cas.c,v 1.26.8.1 2019/12/05 16:50:54 bouyer Exp $ */ |
2 | /* $OpenBSD: if_cas.c,v 1.29 2009/11/29 16:19:38 kettenis Exp $ */ | | 2 | /* $OpenBSD: if_cas.c,v 1.29 2009/11/29 16:19:38 kettenis Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * | | 5 | * |
6 | * Copyright (C) 2007 Mark Kettenis. | | 6 | * Copyright (C) 2007 Mark Kettenis. |
7 | * Copyright (C) 2001 Eduardo Horvath. | | 7 | * Copyright (C) 2001 Eduardo Horvath. |
8 | * All rights reserved. | | 8 | * All rights reserved. |
9 | * | | 9 | * |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -34,27 +34,27 @@ | | | @@ -34,27 +34,27 @@ |
34 | /* | | 34 | /* |
35 | * Driver for Sun Cassini ethernet controllers. | | 35 | * Driver for Sun Cassini ethernet controllers. |
36 | * | | 36 | * |
37 | * There are basically two variants of this chip: Cassini and | | 37 | * There are basically two variants of this chip: Cassini and |
38 | * Cassini+. We can distinguish between the two by revision: 0x10 and | | 38 | * Cassini+. We can distinguish between the two by revision: 0x10 and |
39 | * up are Cassini+. The most important difference is that Cassini+ | | 39 | * up are Cassini+. The most important difference is that Cassini+ |
40 | * has a second RX descriptor ring. Cassini+ will not work without | | 40 | * has a second RX descriptor ring. Cassini+ will not work without |
41 | * configuring that second ring. However, since we don't use it we | | 41 | * configuring that second ring. However, since we don't use it we |
42 | * don't actually fill the descriptors, and only hand off the first | | 42 | * don't actually fill the descriptors, and only hand off the first |
43 | * four to the chip. | | 43 | * four to the chip. |
44 | */ | | 44 | */ |
45 | | | 45 | |
46 | #include <sys/cdefs.h> | | 46 | #include <sys/cdefs.h> |
47 | __KERNEL_RCSID(0, "$NetBSD: if_cas.c,v 1.26 2016/12/15 09:28:05 ozaki-r Exp $"); | | 47 | __KERNEL_RCSID(0, "$NetBSD: if_cas.c,v 1.26.8.1 2019/12/05 16:50:54 bouyer Exp $"); |
48 | | | 48 | |
49 | #ifndef _MODULE | | 49 | #ifndef _MODULE |
50 | #include "opt_inet.h" | | 50 | #include "opt_inet.h" |
51 | #endif | | 51 | #endif |
52 | | | 52 | |
53 | #include <sys/param.h> | | 53 | #include <sys/param.h> |
54 | #include <sys/systm.h> | | 54 | #include <sys/systm.h> |
55 | #include <sys/callout.h> | | 55 | #include <sys/callout.h> |
56 | #include <sys/mbuf.h> | | 56 | #include <sys/mbuf.h> |
57 | #include <sys/syslog.h> | | 57 | #include <sys/syslog.h> |
58 | #include <sys/malloc.h> | | 58 | #include <sys/malloc.h> |
59 | #include <sys/kernel.h> | | 59 | #include <sys/kernel.h> |
60 | #include <sys/socket.h> | | 60 | #include <sys/socket.h> |
| @@ -242,27 +242,27 @@ cas_pci_enaddr(struct cas_softc *sc, str | | | @@ -242,27 +242,27 @@ cas_pci_enaddr(struct cas_softc *sc, str |
242 | vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8); | | 242 | vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8); |
243 | if (vpdoff < 0x1c) | | 243 | if (vpdoff < 0x1c) |
244 | goto fail; | | 244 | goto fail; |
245 | | | 245 | |
246 | next: | | 246 | next: |
247 | bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf)); | | 247 | bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf)); |
248 | if (!PCI_VPDRES_ISLARGE(buf[0])) | | 248 | if (!PCI_VPDRES_ISLARGE(buf[0])) |
249 | goto fail; | | 249 | goto fail; |
250 | | | 250 | |
251 | res = (struct pci_vpd_largeres *)buf; | | 251 | res = (struct pci_vpd_largeres *)buf; |
252 | vpdoff += sizeof(*res); | | 252 | vpdoff += sizeof(*res); |
253 | | | 253 | |
254 | len = ((res->vpdres_len_msb << 8) + res->vpdres_len_lsb); | | 254 | len = ((res->vpdres_len_msb << 8) + res->vpdres_len_lsb); |
255 | switch(PCI_VPDRES_LARGE_NAME(res->vpdres_byte0)) { | | 255 | switch (PCI_VPDRES_LARGE_NAME(res->vpdres_byte0)) { |
256 | case PCI_VPDRES_TYPE_IDENTIFIER_STRING: | | 256 | case PCI_VPDRES_TYPE_IDENTIFIER_STRING: |
257 | /* Skip identifier string. */ | | 257 | /* Skip identifier string. */ |
258 | vpdoff += len; | | 258 | vpdoff += len; |
259 | goto next; | | 259 | goto next; |
260 | | | 260 | |
261 | case PCI_VPDRES_TYPE_VPD: | | 261 | case PCI_VPDRES_TYPE_VPD: |
262 | while (len > 0) { | | 262 | while (len > 0) { |
263 | bus_space_read_region_1(romt, romh, vpdoff, | | 263 | bus_space_read_region_1(romt, romh, vpdoff, |
264 | buf, sizeof(buf)); | | 264 | buf, sizeof(buf)); |
265 | | | 265 | |
266 | vpd = (struct pci_vpd *)buf; | | 266 | vpd = (struct pci_vpd *)buf; |
267 | vpdoff += sizeof(*vpd) + vpd->vpd_len; | | 267 | vpdoff += sizeof(*vpd) + vpd->vpd_len; |
268 | len -= sizeof(*vpd) + vpd->vpd_len; | | 268 | len -= sizeof(*vpd) + vpd->vpd_len; |
| @@ -286,27 +286,27 @@ next: | | | @@ -286,27 +286,27 @@ next: |
286 | * ...that's a byte array with the proper | | 286 | * ...that's a byte array with the proper |
287 | * length for a MAC address... | | 287 | * length for a MAC address... |
288 | */ | | 288 | */ |
289 | if (desc[0] != 'B' || desc[1] != ETHER_ADDR_LEN) | | 289 | if (desc[0] != 'B' || desc[1] != ETHER_ADDR_LEN) |
290 | continue; | | 290 | continue; |
291 | desc += 2; | | 291 | desc += 2; |
292 | | | 292 | |
293 | /* | | 293 | /* |
294 | * ...named "local-mac-address". | | 294 | * ...named "local-mac-address". |
295 | */ | | 295 | */ |
296 | if (strcmp(desc, "local-mac-address") != 0) | | 296 | if (strcmp(desc, "local-mac-address") != 0) |
297 | continue; | | 297 | continue; |
298 | desc += strlen("local-mac-address") + 1; | | 298 | desc += strlen("local-mac-address") + 1; |
299 | | | 299 | |
300 | memcpy(enaddr, desc, ETHER_ADDR_LEN); | | 300 | memcpy(enaddr, desc, ETHER_ADDR_LEN); |
301 | rv = 0; | | 301 | rv = 0; |
302 | } | | 302 | } |
303 | break; | | 303 | break; |
304 | | | 304 | |
305 | default: | | 305 | default: |
306 | goto fail; | | 306 | goto fail; |
307 | } | | 307 | } |
308 | | | 308 | |
309 | fail: | | 309 | fail: |
310 | if (romsize != 0) | | 310 | if (romsize != 0) |
311 | bus_space_unmap(romt, romh, romsize); | | 311 | bus_space_unmap(romt, romh, romsize); |
312 | | | 312 | |
| @@ -413,27 +413,28 @@ cas_config(struct cas_softc *sc, const u | | | @@ -413,27 +413,28 @@ cas_config(struct cas_softc *sc, const u |
413 | /* XXX should map this in with correct endianness */ | | 413 | /* XXX should map this in with correct endianness */ |
414 | if ((error = bus_dmamem_map(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg, | | 414 | if ((error = bus_dmamem_map(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg, |
415 | sizeof(struct cas_control_data), (void **)&sc->sc_control_data, | | 415 | sizeof(struct cas_control_data), (void **)&sc->sc_control_data, |
416 | BUS_DMA_COHERENT)) != 0) { | | 416 | BUS_DMA_COHERENT)) != 0) { |
417 | aprint_error_dev(sc->sc_dev, | | 417 | aprint_error_dev(sc->sc_dev, |
418 | "unable to map control data, error = %d\n", error); | | 418 | "unable to map control data, error = %d\n", error); |
419 | cas_partial_detach(sc, CAS_ATT_1); | | 419 | cas_partial_detach(sc, CAS_ATT_1); |
420 | } | | 420 | } |
421 | | | 421 | |
422 | if ((error = bus_dmamap_create(sc->sc_dmatag, | | 422 | if ((error = bus_dmamap_create(sc->sc_dmatag, |
423 | sizeof(struct cas_control_data), 1, | | 423 | sizeof(struct cas_control_data), 1, |
424 | sizeof(struct cas_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { | | 424 | sizeof(struct cas_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { |
425 | aprint_error_dev(sc->sc_dev, | | 425 | aprint_error_dev(sc->sc_dev, |
426 | "unable to create control data DMA map, error = %d\n", error); | | 426 | "unable to create control data DMA map, error = %d\n", |
| | | 427 | error); |
427 | cas_partial_detach(sc, CAS_ATT_2); | | 428 | cas_partial_detach(sc, CAS_ATT_2); |
428 | } | | 429 | } |
429 | | | 430 | |
430 | if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_cddmamap, | | 431 | if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_cddmamap, |
431 | sc->sc_control_data, sizeof(struct cas_control_data), NULL, | | 432 | sc->sc_control_data, sizeof(struct cas_control_data), NULL, |
432 | 0)) != 0) { | | 433 | 0)) != 0) { |
433 | aprint_error_dev(sc->sc_dev, | | 434 | aprint_error_dev(sc->sc_dev, |
434 | "unable to load control data DMA map, error = %d\n", | | 435 | "unable to load control data DMA map, error = %d\n", |
435 | error); | | 436 | error); |
436 | cas_partial_detach(sc, CAS_ATT_3); | | 437 | cas_partial_detach(sc, CAS_ATT_3); |
437 | } | | 438 | } |
438 | | | 439 | |
439 | memset(sc->sc_control_data, 0, sizeof(struct cas_control_data)); | | 440 | memset(sc->sc_control_data, 0, sizeof(struct cas_control_data)); |
| @@ -530,57 +531,57 @@ cas_config(struct cas_softc *sc, const u | | | @@ -530,57 +531,57 @@ cas_config(struct cas_softc *sc, const u |
530 | mii->mii_writereg = cas_mii_writereg; | | 531 | mii->mii_writereg = cas_mii_writereg; |
531 | mii->mii_statchg = cas_mii_statchg; | | 532 | mii->mii_statchg = cas_mii_statchg; |
532 | | | 533 | |
533 | ifmedia_init(&mii->mii_media, 0, cas_mediachange, cas_mediastatus); | | 534 | ifmedia_init(&mii->mii_media, 0, cas_mediachange, cas_mediastatus); |
534 | sc->sc_ethercom.ec_mii = mii; | | 535 | sc->sc_ethercom.ec_mii = mii; |
535 | | | 536 | |
536 | bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_DATAPATH_MODE, 0); | | 537 | bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_DATAPATH_MODE, 0); |
537 | | | 538 | |
538 | cas_mifinit(sc); | | 539 | cas_mifinit(sc); |
539 | | | 540 | |
540 | if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) { | | 541 | if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) { |
541 | sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL; | | 542 | sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL; |
542 | bus_space_write_4(sc->sc_memt, sc->sc_memh, | | 543 | bus_space_write_4(sc->sc_memt, sc->sc_memh, |
543 | CAS_MIF_CONFIG, sc->sc_mif_config); | | 544 | CAS_MIF_CONFIG, sc->sc_mif_config); |
544 | } | | 545 | } |
545 | | | 546 | |
546 | mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, | | 547 | mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, |
547 | MII_OFFSET_ANY, 0); | | 548 | MII_OFFSET_ANY, 0); |
548 | | | 549 | |
549 | child = LIST_FIRST(&mii->mii_phys); | | 550 | child = LIST_FIRST(&mii->mii_phys); |
550 | if (child == NULL && | | 551 | if (child == NULL && |
551 | sc->sc_mif_config & (CAS_MIF_CONFIG_MDI0|CAS_MIF_CONFIG_MDI1)) { | | 552 | sc->sc_mif_config & (CAS_MIF_CONFIG_MDI0 | CAS_MIF_CONFIG_MDI1)) { |
552 | /* | | 553 | /* |
553 | * Try the external PCS SERDES if we didn't find any | | 554 | * Try the external PCS SERDES if we didn't find any |
554 | * MII devices. | | 555 | * MII devices. |
555 | */ | | 556 | */ |
556 | bus_space_write_4(sc->sc_memt, sc->sc_memh, | | 557 | bus_space_write_4(sc->sc_memt, sc->sc_memh, |
557 | CAS_MII_DATAPATH_MODE, CAS_MII_DATAPATH_SERDES); | | 558 | CAS_MII_DATAPATH_MODE, CAS_MII_DATAPATH_SERDES); |
558 | | | 559 | |
559 | bus_space_write_4(sc->sc_memt, sc->sc_memh, | | 560 | bus_space_write_4(sc->sc_memt, sc->sc_memh, |
560 | CAS_MII_CONFIG, CAS_MII_CONFIG_ENABLE); | | 561 | CAS_MII_CONFIG, CAS_MII_CONFIG_ENABLE); |
561 | | | 562 | |
562 | mii->mii_readreg = cas_pcs_readreg; | | 563 | mii->mii_readreg = cas_pcs_readreg; |
563 | mii->mii_writereg = cas_pcs_writereg; | | 564 | mii->mii_writereg = cas_pcs_writereg; |
564 | | | 565 | |
565 | mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, | | 566 | mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, |
566 | MII_OFFSET_ANY, MIIF_NOISOLATE); | | 567 | MII_OFFSET_ANY, MIIF_NOISOLATE); |
567 | } | | 568 | } |
568 | | | 569 | |
569 | child = LIST_FIRST(&mii->mii_phys); | | 570 | child = LIST_FIRST(&mii->mii_phys); |
570 | if (child == NULL) { | | 571 | if (child == NULL) { |
571 | /* No PHY attached */ | | 572 | /* No PHY attached */ |
572 | ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); | | 573 | ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); |
573 | ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); | | 574 | ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); |
574 | } else { | | 575 | } else { |
575 | /* | | 576 | /* |
576 | * Walk along the list of attached MII devices and | | 577 | * Walk along the list of attached MII devices and |
577 | * establish an `MII instance' to `phy number' | | 578 | * establish an `MII instance' to `phy number' |
578 | * mapping. We'll use this mapping in media change | | 579 | * mapping. We'll use this mapping in media change |
579 | * requests to determine which phy to use to program | | 580 | * requests to determine which phy to use to program |
580 | * the MIF configuration register. | | 581 | * the MIF configuration register. |
581 | */ | | 582 | */ |
582 | for (; child != NULL; child = LIST_NEXT(child, mii_list)) { | | 583 | for (; child != NULL; child = LIST_NEXT(child, mii_list)) { |
583 | /* | | 584 | /* |
584 | * Note: we support just two PHYs: the built-in | | 585 | * Note: we support just two PHYs: the built-in |
585 | * internal device and an external on the MII | | 586 | * internal device and an external on the MII |
586 | * connector. | | 587 | * connector. |
| @@ -591,27 +592,27 @@ cas_config(struct cas_softc *sc, const u | | | @@ -591,27 +592,27 @@ cas_config(struct cas_softc *sc, const u |
591 | " at phy %d, instance %d\n", | | 592 | " at phy %d, instance %d\n", |
592 | device_xname(child->mii_dev), | | 593 | device_xname(child->mii_dev), |
593 | child->mii_phy, child->mii_inst); | | 594 | child->mii_phy, child->mii_inst); |
594 | continue; | | 595 | continue; |
595 | } | | 596 | } |
596 | | | 597 | |
597 | sc->sc_phys[child->mii_inst] = child->mii_phy; | | 598 | sc->sc_phys[child->mii_inst] = child->mii_phy; |
598 | } | | 599 | } |
599 | | | 600 | |
600 | /* | | 601 | /* |
601 | * XXX - we can really do the following ONLY if the | | 602 | * XXX - we can really do the following ONLY if the |
602 | * phy indeed has the auto negotiation capability!! | | 603 | * phy indeed has the auto negotiation capability!! |
603 | */ | | 604 | */ |
604 | ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); | | 605 | ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); |
605 | } | | 606 | } |
606 | | | 607 | |
607 | /* claim 802.1q capability */ | | 608 | /* claim 802.1q capability */ |
608 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | | 609 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; |
609 | | | 610 | |
610 | /* Attach the interface. */ | | 611 | /* Attach the interface. */ |
611 | if_attach(ifp); | | 612 | if_attach(ifp); |
612 | if_deferred_start_init(ifp, NULL); | | 613 | if_deferred_start_init(ifp, NULL); |
613 | ether_ifattach(ifp, enaddr); | | 614 | ether_ifattach(ifp, enaddr); |
614 | | | 615 | |
615 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | | 616 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), |
616 | RND_TYPE_NET, RND_FLAG_DEFAULT); | | 617 | RND_TYPE_NET, RND_FLAG_DEFAULT); |
617 | | | 618 | |
| @@ -964,47 +965,47 @@ cas_disable_tx(struct cas_softc *sc) | | | @@ -964,47 +965,47 @@ cas_disable_tx(struct cas_softc *sc) |
964 | int | | 965 | int |
965 | cas_meminit(struct cas_softc *sc) | | 966 | cas_meminit(struct cas_softc *sc) |
966 | { | | 967 | { |
967 | int i; | | 968 | int i; |
968 | | | 969 | |
969 | /* | | 970 | /* |
970 | * Initialize the transmit descriptor ring. | | 971 | * Initialize the transmit descriptor ring. |
971 | */ | | 972 | */ |
972 | for (i = 0; i < CAS_NTXDESC; i++) { | | 973 | for (i = 0; i < CAS_NTXDESC; i++) { |
973 | sc->sc_txdescs[i].cd_flags = 0; | | 974 | sc->sc_txdescs[i].cd_flags = 0; |
974 | sc->sc_txdescs[i].cd_addr = 0; | | 975 | sc->sc_txdescs[i].cd_addr = 0; |
975 | } | | 976 | } |
976 | CAS_CDTXSYNC(sc, 0, CAS_NTXDESC, | | 977 | CAS_CDTXSYNC(sc, 0, CAS_NTXDESC, |
977 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | | 978 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
978 | | | 979 | |
979 | /* | | 980 | /* |
980 | * Initialize the receive descriptor and receive job | | 981 | * Initialize the receive descriptor and receive job |
981 | * descriptor rings. | | 982 | * descriptor rings. |
982 | */ | | 983 | */ |
983 | for (i = 0; i < CAS_NRXDESC; i++) | | 984 | for (i = 0; i < CAS_NRXDESC; i++) |
984 | CAS_INIT_RXDESC(sc, i, i); | | 985 | CAS_INIT_RXDESC(sc, i, i); |
985 | sc->sc_rxdptr = 0; | | 986 | sc->sc_rxdptr = 0; |
986 | sc->sc_rxptr = 0; | | 987 | sc->sc_rxptr = 0; |
987 | | | 988 | |
988 | /* | | 989 | /* |
989 | * Initialize the receive completion ring. | | 990 | * Initialize the receive completion ring. |
990 | */ | | 991 | */ |
991 | for (i = 0; i < CAS_NRXCOMP; i++) { | | 992 | for (i = 0; i < CAS_NRXCOMP; i++) { |
992 | sc->sc_rxcomps[i].cc_word[0] = 0; | | 993 | sc->sc_rxcomps[i].cc_word[0] = 0; |
993 | sc->sc_rxcomps[i].cc_word[1] = 0; | | 994 | sc->sc_rxcomps[i].cc_word[1] = 0; |
994 | sc->sc_rxcomps[i].cc_word[2] = 0; | | 995 | sc->sc_rxcomps[i].cc_word[2] = 0; |
995 | sc->sc_rxcomps[i].cc_word[3] = CAS_DMA_WRITE(CAS_RC3_OWN); | | 996 | sc->sc_rxcomps[i].cc_word[3] = CAS_DMA_WRITE(CAS_RC3_OWN); |
996 | CAS_CDRXCSYNC(sc, i, | | 997 | CAS_CDRXCSYNC(sc, i, |
997 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | | 998 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
998 | } | | 999 | } |
999 | | | 1000 | |
1000 | return (0); | | 1001 | return (0); |
1001 | } | | 1002 | } |
1002 | | | 1003 | |
1003 | int | | 1004 | int |
1004 | cas_ringsize(int sz) | | 1005 | cas_ringsize(int sz) |
1005 | { | | 1006 | { |
1006 | switch (sz) { | | 1007 | switch (sz) { |
1007 | case 32: | | 1008 | case 32: |
1008 | return CAS_RING_SZ_32; | | 1009 | return CAS_RING_SZ_32; |
1009 | case 64: | | 1010 | case 64: |
1010 | return CAS_RING_SZ_64; | | 1011 | return CAS_RING_SZ_64; |
| @@ -1079,71 +1080,71 @@ cas_init(struct ifnet *ifp) | | | @@ -1079,71 +1080,71 @@ cas_init(struct ifnet *ifp) |
1079 | | | 1080 | |
1080 | /* step 4. TX MAC registers & counters */ | | 1081 | /* step 4. TX MAC registers & counters */ |
1081 | cas_init_regs(sc); | | 1082 | cas_init_regs(sc); |
1082 | max_frame_size = ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN; | | 1083 | max_frame_size = ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN; |
1083 | v = (max_frame_size) | (0x2000 << 16) /* Burst size */; | | 1084 | v = (max_frame_size) | (0x2000 << 16) /* Burst size */; |
1084 | bus_space_write_4(t, h, CAS_MAC_MAC_MAX_FRAME, v); | | 1085 | bus_space_write_4(t, h, CAS_MAC_MAC_MAX_FRAME, v); |
1085 | | | 1086 | |
1086 | /* step 5. RX MAC registers & counters */ | | 1087 | /* step 5. RX MAC registers & counters */ |
1087 | cas_iff(sc); | | 1088 | cas_iff(sc); |
1088 | | | 1089 | |
1089 | /* step 6 & 7. Program Descriptor Ring Base Addresses */ | | 1090 | /* step 6 & 7. Program Descriptor Ring Base Addresses */ |
1090 | KASSERT((CAS_CDTXADDR(sc, 0) & 0x1fff) == 0); | | 1091 | KASSERT((CAS_CDTXADDR(sc, 0) & 0x1fff) == 0); |
1091 | bus_space_write_4(t, h, CAS_TX_RING_PTR_HI, | | 1092 | bus_space_write_4(t, h, CAS_TX_RING_PTR_HI, |
1092 | (((uint64_t)CAS_CDTXADDR(sc,0)) >> 32)); | | 1093 | (((uint64_t)CAS_CDTXADDR(sc, 0)) >> 32)); |
1093 | bus_space_write_4(t, h, CAS_TX_RING_PTR_LO, CAS_CDTXADDR(sc, 0)); | | 1094 | bus_space_write_4(t, h, CAS_TX_RING_PTR_LO, CAS_CDTXADDR(sc, 0)); |
1094 | | | 1095 | |
1095 | KASSERT((CAS_CDRXADDR(sc, 0) & 0x1fff) == 0); | | 1096 | KASSERT((CAS_CDRXADDR(sc, 0) & 0x1fff) == 0); |
1096 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_HI, | | 1097 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_HI, |
1097 | (((uint64_t)CAS_CDRXADDR(sc,0)) >> 32)); | | 1098 | (((uint64_t)CAS_CDRXADDR(sc, 0)) >> 32)); |
1098 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_LO, CAS_CDRXADDR(sc, 0)); | | 1099 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_LO, CAS_CDRXADDR(sc, 0)); |
1099 | | | 1100 | |
1100 | KASSERT((CAS_CDRXCADDR(sc, 0) & 0x1fff) == 0); | | 1101 | KASSERT((CAS_CDRXCADDR(sc, 0) & 0x1fff) == 0); |
1101 | bus_space_write_4(t, h, CAS_RX_CRING_PTR_HI, | | 1102 | bus_space_write_4(t, h, CAS_RX_CRING_PTR_HI, |
1102 | (((uint64_t)CAS_CDRXCADDR(sc,0)) >> 32)); | | 1103 | (((uint64_t)CAS_CDRXCADDR(sc, 0)) >> 32)); |
1103 | bus_space_write_4(t, h, CAS_RX_CRING_PTR_LO, CAS_CDRXCADDR(sc, 0)); | | 1104 | bus_space_write_4(t, h, CAS_RX_CRING_PTR_LO, CAS_CDRXCADDR(sc, 0)); |
1104 | | | 1105 | |
1105 | if (CAS_PLUS(sc)) { | | 1106 | if (CAS_PLUS(sc)) { |
1106 | KASSERT((CAS_CDRXADDR2(sc, 0) & 0x1fff) == 0); | | 1107 | KASSERT((CAS_CDRXADDR2(sc, 0) & 0x1fff) == 0); |
1107 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_HI2, | | 1108 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_HI2, |
1108 | (((uint64_t)CAS_CDRXADDR2(sc,0)) >> 32)); | | 1109 | (((uint64_t)CAS_CDRXADDR2(sc, 0)) >> 32)); |
1109 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_LO2, | | 1110 | bus_space_write_4(t, h, CAS_RX_DRING_PTR_LO2, |
1110 | CAS_CDRXADDR2(sc, 0)); | | 1111 | CAS_CDRXADDR2(sc, 0)); |
1111 | } | | 1112 | } |
1112 | | | 1113 | |
1113 | /* step 8. Global Configuration & Interrupt Mask */ | | 1114 | /* step 8. Global Configuration & Interrupt Mask */ |
1114 | cas_estintr(sc, CAS_INTR_REG); | | 1115 | cas_estintr(sc, CAS_INTR_REG); |
1115 | | | 1116 | |
1116 | /* step 9. ETX Configuration: use mostly default values */ | | 1117 | /* step 9. ETX Configuration: use mostly default values */ |
1117 | | | 1118 | |
1118 | /* Enable DMA */ | | 1119 | /* Enable DMA */ |
1119 | v = cas_ringsize(CAS_NTXDESC /*XXX*/) << 10; | | 1120 | v = cas_ringsize(CAS_NTXDESC /*XXX*/) << 10; |
1120 | bus_space_write_4(t, h, CAS_TX_CONFIG, | | 1121 | bus_space_write_4(t, h, CAS_TX_CONFIG, |
1121 | v|CAS_TX_CONFIG_TXDMA_EN|(1<<24)|(1<<29)); | | 1122 | v | CAS_TX_CONFIG_TXDMA_EN | (1 << 24) | (1 << 29)); |
1122 | bus_space_write_4(t, h, CAS_TX_KICK, 0); | | 1123 | bus_space_write_4(t, h, CAS_TX_KICK, 0); |
1123 | | | 1124 | |
1124 | /* step 10. ERX Configuration */ | | 1125 | /* step 10. ERX Configuration */ |
1125 | | | 1126 | |
1126 | /* Encode Receive Descriptor ring size */ | | 1127 | /* Encode Receive Descriptor ring size */ |
1127 | v = cas_ringsize(CAS_NRXDESC) << CAS_RX_CONFIG_RXDRNG_SZ_SHIFT; | | 1128 | v = cas_ringsize(CAS_NRXDESC) << CAS_RX_CONFIG_RXDRNG_SZ_SHIFT; |
1128 | if (CAS_PLUS(sc)) | | 1129 | if (CAS_PLUS(sc)) |
1129 | v |= cas_ringsize(32) << CAS_RX_CONFIG_RXDRNG2_SZ_SHIFT; | | 1130 | v |= cas_ringsize(32) << CAS_RX_CONFIG_RXDRNG2_SZ_SHIFT; |
1130 | | | 1131 | |
1131 | /* Encode Receive Completion ring size */ | | 1132 | /* Encode Receive Completion ring size */ |
1132 | v |= cas_cringsize(CAS_NRXCOMP) << CAS_RX_CONFIG_RXCRNG_SZ_SHIFT; | | 1133 | v |= cas_cringsize(CAS_NRXCOMP) << CAS_RX_CONFIG_RXCRNG_SZ_SHIFT; |
1133 | | | 1134 | |
1134 | /* Enable DMA */ | | 1135 | /* Enable DMA */ |
1135 | bus_space_write_4(t, h, CAS_RX_CONFIG, | | 1136 | bus_space_write_4(t, h, CAS_RX_CONFIG, |
1136 | v|(2<<CAS_RX_CONFIG_FBOFF_SHFT)|CAS_RX_CONFIG_RXDMA_EN); | | 1137 | v|(2<<CAS_RX_CONFIG_FBOFF_SHFT) | CAS_RX_CONFIG_RXDMA_EN); |
1137 | | | 1138 | |
1138 | /* | | 1139 | /* |
1139 | * The following value is for an OFF Threshold of about 3/4 full | | 1140 | * The following value is for an OFF Threshold of about 3/4 full |
1140 | * and an ON Threshold of 1/4 full. | | 1141 | * and an ON Threshold of 1/4 full. |
1141 | */ | | 1142 | */ |
1142 | bus_space_write_4(t, h, CAS_RX_PAUSE_THRESH, | | 1143 | bus_space_write_4(t, h, CAS_RX_PAUSE_THRESH, |
1143 | (3 * sc->sc_rxfifosize / 256) | | | 1144 | (3 * sc->sc_rxfifosize / 256) | |
1144 | ((sc->sc_rxfifosize / 256) << 12)); | | 1145 | ((sc->sc_rxfifosize / 256) << 12)); |
1145 | bus_space_write_4(t, h, CAS_RX_BLANKING, (6 << 12) | 6); | | 1146 | bus_space_write_4(t, h, CAS_RX_BLANKING, (6 << 12) | 6); |
1146 | | | 1147 | |
1147 | /* step 11. Configure Media */ | | 1148 | /* step 11. Configure Media */ |
1148 | mii_ifmedia_change(&sc->sc_mii); | | 1149 | mii_ifmedia_change(&sc->sc_mii); |
1149 | | | 1150 | |
| @@ -1255,52 +1256,52 @@ cas_rint(struct cas_softc *sc) | | | @@ -1255,52 +1256,52 @@ cas_rint(struct cas_softc *sc) |
1255 | { | | 1256 | { |
1256 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1257 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1257 | bus_space_tag_t t = sc->sc_memt; | | 1258 | bus_space_tag_t t = sc->sc_memt; |
1258 | bus_space_handle_t h = sc->sc_memh; | | 1259 | bus_space_handle_t h = sc->sc_memh; |
1259 | struct cas_rxsoft *rxs; | | 1260 | struct cas_rxsoft *rxs; |
1260 | struct mbuf *m; | | 1261 | struct mbuf *m; |
1261 | u_int64_t word[4]; | | 1262 | u_int64_t word[4]; |
1262 | int len, off, idx; | | 1263 | int len, off, idx; |
1263 | int i, skip; | | 1264 | int i, skip; |
1264 | void *cp; | | 1265 | void *cp; |
1265 | | | 1266 | |
1266 | for (i = sc->sc_rxptr;; i = CAS_NEXTRX(i + skip)) { | | 1267 | for (i = sc->sc_rxptr;; i = CAS_NEXTRX(i + skip)) { |
1267 | CAS_CDRXCSYNC(sc, i, | | 1268 | CAS_CDRXCSYNC(sc, i, |
1268 | BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); | | 1269 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1269 | | | 1270 | |
1270 | word[0] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[0]); | | 1271 | word[0] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[0]); |
1271 | word[1] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[1]); | | 1272 | word[1] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[1]); |
1272 | word[2] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[2]); | | 1273 | word[2] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[2]); |
1273 | word[3] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[3]); | | 1274 | word[3] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[3]); |
1274 | | | 1275 | |
1275 | /* Stop if the hardware still owns the descriptor. */ | | 1276 | /* Stop if the hardware still owns the descriptor. */ |
1276 | if ((word[0] & CAS_RC0_TYPE) == 0 || word[3] & CAS_RC3_OWN) | | 1277 | if ((word[0] & CAS_RC0_TYPE) == 0 || word[3] & CAS_RC3_OWN) |
1277 | break; | | 1278 | break; |
1278 | | | 1279 | |
1279 | len = CAS_RC1_HDR_LEN(word[1]); | | 1280 | len = CAS_RC1_HDR_LEN(word[1]); |
1280 | if (len > 0) { | | 1281 | if (len > 0) { |
1281 | off = CAS_RC1_HDR_OFF(word[1]); | | 1282 | off = CAS_RC1_HDR_OFF(word[1]); |
1282 | idx = CAS_RC1_HDR_IDX(word[1]); | | 1283 | idx = CAS_RC1_HDR_IDX(word[1]); |
1283 | rxs = &sc->sc_rxsoft[idx]; | | 1284 | rxs = &sc->sc_rxsoft[idx]; |
1284 | | | 1285 | |
1285 | DPRINTF(sc, ("hdr at idx %d, off %d, len %d\n", | | 1286 | DPRINTF(sc, ("hdr at idx %d, off %d, len %d\n", |
1286 | idx, off, len)); | | 1287 | idx, off, len)); |
1287 | | | 1288 | |
1288 | bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0, | | 1289 | bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0, |
1289 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); | | 1290 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); |
1290 | | | 1291 | |
1291 | cp = rxs->rxs_kva + off * 256 + ETHER_ALIGN; | | 1292 | cp = rxs->rxs_kva + off * 256 + ETHER_ALIGN; |
1292 | m = m_devget(cp, len, 0, ifp, NULL); | | 1293 | m = m_devget(cp, len, 0, ifp, NULL); |
1293 | | | 1294 | |
1294 | if (word[0] & CAS_RC0_RELEASE_HDR) | | 1295 | if (word[0] & CAS_RC0_RELEASE_HDR) |
1295 | cas_add_rxbuf(sc, idx); | | 1296 | cas_add_rxbuf(sc, idx); |
1296 | | | 1297 | |
1297 | if (m != NULL) { | | 1298 | if (m != NULL) { |
1298 | | | 1299 | |
1299 | /* | | 1300 | /* |
1300 | * Pass this up to any BPF listeners, but only | | 1301 | * Pass this up to any BPF listeners, but only |
1301 | * pass it up the stack if its for us. | | 1302 | * pass it up the stack if its for us. |
1302 | */ | | 1303 | */ |
1303 | m->m_pkthdr.csum_flags = 0; | | 1304 | m->m_pkthdr.csum_flags = 0; |
1304 | if_percpuq_enqueue(ifp->if_percpuq, m); | | 1305 | if_percpuq_enqueue(ifp->if_percpuq, m); |
1305 | } else | | 1306 | } else |
1306 | ifp->if_ierrors++; | | 1307 | ifp->if_ierrors++; |
| @@ -1339,27 +1340,27 @@ cas_rint(struct cas_softc *sc) | | | @@ -1339,27 +1340,27 @@ cas_rint(struct cas_softc *sc) |
1339 | if (word[0] & CAS_RC0_SPLIT) | | 1340 | if (word[0] & CAS_RC0_SPLIT) |
1340 | aprint_error_dev(sc->sc_dev, "split packet\n"); | | 1341 | aprint_error_dev(sc->sc_dev, "split packet\n"); |
1341 | | | 1342 | |
1342 | skip = CAS_RC0_SKIP(word[0]); | | 1343 | skip = CAS_RC0_SKIP(word[0]); |
1343 | } | | 1344 | } |
1344 | | | 1345 | |
1345 | while (sc->sc_rxptr != i) { | | 1346 | while (sc->sc_rxptr != i) { |
1346 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[0] = 0; | | 1347 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[0] = 0; |
1347 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[1] = 0; | | 1348 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[1] = 0; |
1348 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[2] = 0; | | 1349 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[2] = 0; |
1349 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[3] = | | 1350 | sc->sc_rxcomps[sc->sc_rxptr].cc_word[3] = |
1350 | CAS_DMA_WRITE(CAS_RC3_OWN); | | 1351 | CAS_DMA_WRITE(CAS_RC3_OWN); |
1351 | CAS_CDRXCSYNC(sc, sc->sc_rxptr, | | 1352 | CAS_CDRXCSYNC(sc, sc->sc_rxptr, |
1352 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | | 1353 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
1353 | | | 1354 | |
1354 | sc->sc_rxptr = CAS_NEXTRX(sc->sc_rxptr); | | 1355 | sc->sc_rxptr = CAS_NEXTRX(sc->sc_rxptr); |
1355 | } | | 1356 | } |
1356 | | | 1357 | |
1357 | bus_space_write_4(t, h, CAS_RX_COMP_TAIL, sc->sc_rxptr); | | 1358 | bus_space_write_4(t, h, CAS_RX_COMP_TAIL, sc->sc_rxptr); |
1358 | | | 1359 | |
1359 | DPRINTF(sc, ("cas_rint: done sc->rxptr %d, complete %d\n", | | 1360 | DPRINTF(sc, ("cas_rint: done sc->rxptr %d, complete %d\n", |
1360 | sc->sc_rxptr, bus_space_read_4(t, h, CAS_RX_COMPLETION))); | | 1361 | sc->sc_rxptr, bus_space_read_4(t, h, CAS_RX_COMPLETION))); |
1361 | | | 1362 | |
1362 | return (1); | | 1363 | return (1); |
1363 | } | | 1364 | } |
1364 | | | 1365 | |
1365 | /* | | 1366 | /* |
| @@ -1606,30 +1607,30 @@ cas_mii_statchg(struct ifnet *ifp) | | | @@ -1606,30 +1607,30 @@ cas_mii_statchg(struct ifnet *ifp) |
1606 | bus_space_tag_t t = sc->sc_memt; | | 1607 | bus_space_tag_t t = sc->sc_memt; |
1607 | bus_space_handle_t mac = sc->sc_memh; | | 1608 | bus_space_handle_t mac = sc->sc_memh; |
1608 | u_int32_t v; | | 1609 | u_int32_t v; |
1609 | | | 1610 | |
1610 | #ifdef CAS_DEBUG | | 1611 | #ifdef CAS_DEBUG |
1611 | if (sc->sc_debug) | | 1612 | if (sc->sc_debug) |
1612 | printf("cas_mii_statchg: status change: phy = %d\n", | | 1613 | printf("cas_mii_statchg: status change: phy = %d\n", |
1613 | sc->sc_phys[instance]); | | 1614 | sc->sc_phys[instance]); |
1614 | #endif | | 1615 | #endif |
1615 | | | 1616 | |
1616 | /* Set tx full duplex options */ | | 1617 | /* Set tx full duplex options */ |
1617 | bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, 0); | | 1618 | bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, 0); |
1618 | delay(10000); /* reg must be cleared and delay before changing. */ | | 1619 | delay(10000); /* reg must be cleared and delay before changing. */ |
1619 | v = CAS_MAC_TX_ENA_IPG0|CAS_MAC_TX_NGU|CAS_MAC_TX_NGU_LIMIT| | | 1620 | v = CAS_MAC_TX_ENA_IPG0 | CAS_MAC_TX_NGU | CAS_MAC_TX_NGU_LIMIT | |
1620 | CAS_MAC_TX_ENABLE; | | 1621 | CAS_MAC_TX_ENABLE; |
1621 | if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) { | | 1622 | if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) { |
1622 | v |= CAS_MAC_TX_IGN_CARRIER|CAS_MAC_TX_IGN_COLLIS; | | 1623 | v |= CAS_MAC_TX_IGN_CARRIER | CAS_MAC_TX_IGN_COLLIS; |
1623 | } | | 1624 | } |
1624 | bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, v); | | 1625 | bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, v); |
1625 | | | 1626 | |
1626 | /* XIF Configuration */ | | 1627 | /* XIF Configuration */ |
1627 | v = CAS_MAC_XIF_TX_MII_ENA; | | 1628 | v = CAS_MAC_XIF_TX_MII_ENA; |
1628 | v |= CAS_MAC_XIF_LINK_LED; | | 1629 | v |= CAS_MAC_XIF_LINK_LED; |
1629 | | | 1630 | |
1630 | /* MII needs echo disable if half duplex. */ | | 1631 | /* MII needs echo disable if half duplex. */ |
1631 | if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) | | 1632 | if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) |
1632 | /* turn on full duplex LED */ | | 1633 | /* turn on full duplex LED */ |
1633 | v |= CAS_MAC_XIF_FDPLX_LED; | | 1634 | v |= CAS_MAC_XIF_FDPLX_LED; |
1634 | else | | 1635 | else |
1635 | /* half duplex -- disable echo */ | | 1636 | /* half duplex -- disable echo */ |
| @@ -1665,27 +1666,27 @@ cas_pcs_readreg(device_t self, int phy, | | | @@ -1665,27 +1666,27 @@ cas_pcs_readreg(device_t self, int phy, |
1665 | case MII_BMCR: | | 1666 | case MII_BMCR: |
1666 | reg = CAS_MII_CONTROL; | | 1667 | reg = CAS_MII_CONTROL; |
1667 | break; | | 1668 | break; |
1668 | case MII_BMSR: | | 1669 | case MII_BMSR: |
1669 | reg = CAS_MII_STATUS; | | 1670 | reg = CAS_MII_STATUS; |
1670 | break; | | 1671 | break; |
1671 | case MII_ANAR: | | 1672 | case MII_ANAR: |
1672 | reg = CAS_MII_ANAR; | | 1673 | reg = CAS_MII_ANAR; |
1673 | break; | | 1674 | break; |
1674 | case MII_ANLPAR: | | 1675 | case MII_ANLPAR: |
1675 | reg = CAS_MII_ANLPAR; | | 1676 | reg = CAS_MII_ANLPAR; |
1676 | break; | | 1677 | break; |
1677 | case MII_EXTSR: | | 1678 | case MII_EXTSR: |
1678 | return (EXTSR_1000XFDX|EXTSR_1000XHDX); | | 1679 | return (EXTSR_1000XFDX | EXTSR_1000XHDX); |
1679 | default: | | 1680 | default: |
1680 | return (0); | | 1681 | return (0); |
1681 | } | | 1682 | } |
1682 | | | 1683 | |
1683 | return bus_space_read_4(t, pcs, reg); | | 1684 | return bus_space_read_4(t, pcs, reg); |
1684 | } | | 1685 | } |
1685 | | | 1686 | |
1686 | void | | 1687 | void |
1687 | cas_pcs_writereg(device_t self, int phy, int reg, int val) | | 1688 | cas_pcs_writereg(device_t self, int phy, int reg, int val) |
1688 | { | | 1689 | { |
1689 | struct cas_softc *sc = device_private(self); | | 1690 | struct cas_softc *sc = device_private(self); |
1690 | bus_space_tag_t t = sc->sc_memt; | | 1691 | bus_space_tag_t t = sc->sc_memt; |
1691 | bus_space_handle_t pcs = sc->sc_memh; | | 1692 | bus_space_handle_t pcs = sc->sc_memh; |
| @@ -1826,35 +1827,35 @@ cas_estintr(struct cas_softc *sc, int wh | | | @@ -1826,35 +1827,35 @@ cas_estintr(struct cas_softc *sc, int wh |
1826 | "unable to establish interrupt"); | | 1827 | "unable to establish interrupt"); |
1827 | if (intrstr != NULL) | | 1828 | if (intrstr != NULL) |
1828 | aprint_error(" at %s", intrstr); | | 1829 | aprint_error(" at %s", intrstr); |
1829 | aprint_error("\n"); | | 1830 | aprint_error("\n"); |
1830 | return false; | | 1831 | return false; |
1831 | } | | 1832 | } |
1832 | | | 1833 | |
1833 | aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); | | 1834 | aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); |
1834 | } | | 1835 | } |
1835 | | | 1836 | |
1836 | /* Interrupt register */ | | 1837 | /* Interrupt register */ |
1837 | if (what & CAS_INTR_REG) { | | 1838 | if (what & CAS_INTR_REG) { |
1838 | bus_space_write_4(t, h, CAS_INTMASK, | | 1839 | bus_space_write_4(t, h, CAS_INTMASK, |
1839 | ~(CAS_INTR_TX_INTME|CAS_INTR_TX_EMPTY| | | 1840 | ~(CAS_INTR_TX_INTME | CAS_INTR_TX_EMPTY | |
1840 | CAS_INTR_TX_TAG_ERR| | | 1841 | CAS_INTR_TX_TAG_ERR | |
1841 | CAS_INTR_RX_DONE|CAS_INTR_RX_NOBUF| | | 1842 | CAS_INTR_RX_DONE | CAS_INTR_RX_NOBUF | |
1842 | CAS_INTR_RX_TAG_ERR| | | 1843 | CAS_INTR_RX_TAG_ERR | |
1843 | CAS_INTR_RX_COMP_FULL|CAS_INTR_PCS| | | 1844 | CAS_INTR_RX_COMP_FULL | CAS_INTR_PCS | |
1844 | CAS_INTR_MAC_CONTROL|CAS_INTR_MIF| | | 1845 | CAS_INTR_MAC_CONTROL | CAS_INTR_MIF | |
1845 | CAS_INTR_BERR)); | | 1846 | CAS_INTR_BERR)); |
1846 | bus_space_write_4(t, h, CAS_MAC_RX_MASK, | | 1847 | bus_space_write_4(t, h, CAS_MAC_RX_MASK, |
1847 | CAS_MAC_RX_DONE|CAS_MAC_RX_FRAME_CNT); | | 1848 | CAS_MAC_RX_DONE | CAS_MAC_RX_FRAME_CNT); |
1848 | bus_space_write_4(t, h, CAS_MAC_TX_MASK, CAS_MAC_TX_XMIT_DONE); | | 1849 | bus_space_write_4(t, h, CAS_MAC_TX_MASK, CAS_MAC_TX_XMIT_DONE); |
1849 | bus_space_write_4(t, h, CAS_MAC_CONTROL_MASK, 0); /* XXXX */ | | 1850 | bus_space_write_4(t, h, CAS_MAC_CONTROL_MASK, 0); /* XXXX */ |
1850 | } | | 1851 | } |
1851 | return true; | | 1852 | return true; |
1852 | } | | 1853 | } |
1853 | | | 1854 | |
1854 | bool | | 1855 | bool |
1855 | cas_shutdown(device_t self, int howto) | | 1856 | cas_shutdown(device_t self, int howto) |
1856 | { | | 1857 | { |
1857 | struct cas_softc *sc = device_private(self); | | 1858 | struct cas_softc *sc = device_private(self); |
1858 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1859 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1859 | | | 1860 | |
1860 | cas_stop(ifp, 1); | | 1861 | cas_stop(ifp, 1); |
| @@ -1869,70 +1870,80 @@ cas_iff(struct cas_softc *sc) | | | @@ -1869,70 +1870,80 @@ cas_iff(struct cas_softc *sc) |
1869 | struct ethercom *ec = &sc->sc_ethercom; | | 1870 | struct ethercom *ec = &sc->sc_ethercom; |
1870 | struct ether_multi *enm; | | 1871 | struct ether_multi *enm; |
1871 | struct ether_multistep step; | | 1872 | struct ether_multistep step; |
1872 | bus_space_tag_t t = sc->sc_memt; | | 1873 | bus_space_tag_t t = sc->sc_memt; |
1873 | bus_space_handle_t h = sc->sc_memh; | | 1874 | bus_space_handle_t h = sc->sc_memh; |
1874 | u_int32_t crc, hash[16], rxcfg; | | 1875 | u_int32_t crc, hash[16], rxcfg; |
1875 | int i; | | 1876 | int i; |
1876 | | | 1877 | |
1877 | rxcfg = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG); | | 1878 | rxcfg = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG); |
1878 | rxcfg &= ~(CAS_MAC_RX_HASH_FILTER | CAS_MAC_RX_PROMISCUOUS | | | 1879 | rxcfg &= ~(CAS_MAC_RX_HASH_FILTER | CAS_MAC_RX_PROMISCUOUS | |
1879 | CAS_MAC_RX_PROMISC_GRP); | | 1880 | CAS_MAC_RX_PROMISC_GRP); |
1880 | ifp->if_flags &= ~IFF_ALLMULTI; | | 1881 | ifp->if_flags &= ~IFF_ALLMULTI; |
1881 | | | 1882 | |
1882 | if (ifp->if_flags & IFF_PROMISC || ec->ec_multicnt > 0) { | | 1883 | if ((ifp->if_flags & IFF_PROMISC) != 0) |
1883 | ifp->if_flags |= IFF_ALLMULTI; | | 1884 | goto update; |
1884 | if (ifp->if_flags & IFF_PROMISC) | | | |
1885 | rxcfg |= CAS_MAC_RX_PROMISCUOUS; | | | |
1886 | else | | | |
1887 | rxcfg |= CAS_MAC_RX_PROMISC_GRP; | | | |
1888 | } else { | | | |
1889 | /* | | | |
1890 | * Set up multicast address filter by passing all multicast | | | |
1891 | * addresses through a crc generator, and then using the | | | |
1892 | * high order 8 bits as an index into the 256 bit logical | | | |
1893 | * address filter. The high order 4 bits selects the word, | | | |
1894 | * while the other 4 bits select the bit within the word | | | |
1895 | * (where bit 0 is the MSB). | | | |
1896 | */ | | | |
1897 | | | 1885 | |
1898 | rxcfg |= CAS_MAC_RX_HASH_FILTER; | | 1886 | /* |
| | | 1887 | * Set up multicast address filter by passing all multicast |
| | | 1888 | * addresses through a crc generator, and then using the |
| | | 1889 | * high order 8 bits as an index into the 256 bit logical |
| | | 1890 | * address filter. The high order 4 bits selects the word, |
| | | 1891 | * while the other 4 bits select the bit within the word |
| | | 1892 | * (where bit 0 is the MSB). |
| | | 1893 | */ |
1899 | | | 1894 | |
1900 | /* Clear hash table */ | | 1895 | /* Clear hash table */ |
1901 | for (i = 0; i < 16; i++) | | 1896 | for (i = 0; i < 16; i++) |
1902 | hash[i] = 0; | | 1897 | hash[i] = 0; |
| | | 1898 | |
| | | 1899 | ETHER_FIRST_MULTI(step, ec, enm); |
| | | 1900 | while (enm != NULL) { |
| | | 1901 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { |
| | | 1902 | /* XXX Use ETHER_F_ALLMULTI in future. */ |
| | | 1903 | ifp->if_flags |= IFF_ALLMULTI; |
| | | 1904 | ETHER_UNLOCK(ec); |
| | | 1905 | goto update; |
| | | 1906 | } |
1903 | | | 1907 | |
1904 | ETHER_FIRST_MULTI(step, ec, enm); | | 1908 | crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); |
1905 | while (enm != NULL) { | | | |
1906 | crc = ether_crc32_le(enm->enm_addrlo, | | | |
1907 | ETHER_ADDR_LEN); | | | |
1908 | | | 1909 | |
1909 | /* Just want the 8 most significant bits. */ | | 1910 | /* Just want the 8 most significant bits. */ |
1910 | crc >>= 24; | | 1911 | crc >>= 24; |
1911 | | | 1912 | |
1912 | /* Set the corresponding bit in the filter. */ | | 1913 | /* Set the corresponding bit in the filter. */ |
1913 | hash[crc >> 4] |= 1 << (15 - (crc & 15)); | | 1914 | hash[crc >> 4] |= 1 << (15 - (crc & 15)); |
1914 | | | 1915 | |
1915 | ETHER_NEXT_MULTI(step, enm); | | 1916 | ETHER_NEXT_MULTI(step, enm); |
1916 | } | | 1917 | } |
1917 | | | 1918 | |
1918 | /* Now load the hash table into the chip (if we are using it) */ | | 1919 | rxcfg |= CAS_MAC_RX_HASH_FILTER; |
1919 | for (i = 0; i < 16; i++) { | | 1920 | |
1920 | bus_space_write_4(t, h, | | 1921 | /* Now load the hash table into the chip (if we are using it) */ |
1921 | CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0), | | 1922 | for (i = 0; i < 16; i++) { |
1922 | hash[i]); | | 1923 | bus_space_write_4(t, h, |
1923 | } | | 1924 | CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0), |
| | | 1925 | hash[i]); |
1924 | } | | 1926 | } |
1925 | | | 1927 | |
| | | 1928 | update: |
| | | 1929 | if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { |
| | | 1930 | if (ifp->if_flags & IFF_PROMISC) { |
| | | 1931 | rxcfg |= CAS_MAC_RX_PROMISCUOUS; |
| | | 1932 | /* XXX Use ETHER_F_ALLMULTI in future. */ |
| | | 1933 | ifp->if_flags |= IFF_ALLMULTI; |
| | | 1934 | } else |
| | | 1935 | rxcfg |= CAS_MAC_RX_PROMISC_GRP; |
| | | 1936 | } |
1926 | bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, rxcfg); | | 1937 | bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, rxcfg); |
1927 | } | | 1938 | } |
1928 | | | 1939 | |
1929 | int | | 1940 | int |
1930 | cas_encap(struct cas_softc *sc, struct mbuf *mhead, u_int32_t *bixp) | | 1941 | cas_encap(struct cas_softc *sc, struct mbuf *mhead, u_int32_t *bixp) |
1931 | { | | 1942 | { |
1932 | u_int64_t flags; | | 1943 | u_int64_t flags; |
1933 | u_int32_t cur, frag, i; | | 1944 | u_int32_t cur, frag, i; |
1934 | bus_dmamap_t map; | | 1945 | bus_dmamap_t map; |
1935 | | | 1946 | |
1936 | cur = frag = *bixp; | | 1947 | cur = frag = *bixp; |
1937 | map = sc->sc_txd[cur].sd_map; | | 1948 | map = sc->sc_txd[cur].sd_map; |
1938 | | | 1949 | |