1*2d586421SSepherosa Ziehau /****************************************************************************** 2*2d586421SSepherosa Ziehau * 3*2d586421SSepherosa Ziehau * Name : sky2.c 4*2d586421SSepherosa Ziehau * Project: Gigabit Ethernet Driver for FreeBSD 5.x/6.x 5*2d586421SSepherosa Ziehau * Version: $Revision: 1.23 $ 6*2d586421SSepherosa Ziehau * Date : $Date: 2005/12/22 09:04:11 $ 7*2d586421SSepherosa Ziehau * Purpose: Main driver source file 8*2d586421SSepherosa Ziehau * 9*2d586421SSepherosa Ziehau *****************************************************************************/ 10*2d586421SSepherosa Ziehau 11*2d586421SSepherosa Ziehau /****************************************************************************** 12*2d586421SSepherosa Ziehau * 13*2d586421SSepherosa Ziehau * LICENSE: 14*2d586421SSepherosa Ziehau * Copyright (C) Marvell International Ltd. and/or its affiliates 15*2d586421SSepherosa Ziehau * 16*2d586421SSepherosa Ziehau * The computer program files contained in this folder ("Files") 17*2d586421SSepherosa Ziehau * are provided to you under the BSD-type license terms provided 18*2d586421SSepherosa Ziehau * below, and any use of such Files and any derivative works 19*2d586421SSepherosa Ziehau * thereof created by you shall be governed by the following terms 20*2d586421SSepherosa Ziehau * and conditions: 21*2d586421SSepherosa Ziehau * 22*2d586421SSepherosa Ziehau * - Redistributions of source code must retain the above copyright 23*2d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 24*2d586421SSepherosa Ziehau * - Redistributions in binary form must reproduce the above 25*2d586421SSepherosa Ziehau * copyright notice, this list of conditions and the following 26*2d586421SSepherosa Ziehau * disclaimer in the documentation and/or other materials provided 27*2d586421SSepherosa Ziehau * with the distribution. 28*2d586421SSepherosa Ziehau * - Neither the name of Marvell nor the names of its contributors 29*2d586421SSepherosa Ziehau * may be used to endorse or promote products derived from this 30*2d586421SSepherosa Ziehau * software without specific prior written permission. 31*2d586421SSepherosa Ziehau * 32*2d586421SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*2d586421SSepherosa Ziehau * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*2d586421SSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35*2d586421SSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 36*2d586421SSepherosa Ziehau * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 37*2d586421SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 38*2d586421SSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39*2d586421SSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40*2d586421SSepherosa Ziehau * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 41*2d586421SSepherosa Ziehau * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42*2d586421SSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 43*2d586421SSepherosa Ziehau * OF THE POSSIBILITY OF SUCH DAMAGE. 44*2d586421SSepherosa Ziehau * /LICENSE 45*2d586421SSepherosa Ziehau * 46*2d586421SSepherosa Ziehau *****************************************************************************/ 47*2d586421SSepherosa Ziehau 48*2d586421SSepherosa Ziehau /*- 49*2d586421SSepherosa Ziehau * Copyright (c) 1997, 1998, 1999, 2000 50*2d586421SSepherosa Ziehau * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 51*2d586421SSepherosa Ziehau * 52*2d586421SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 53*2d586421SSepherosa Ziehau * modification, are permitted provided that the following conditions 54*2d586421SSepherosa Ziehau * are met: 55*2d586421SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 56*2d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 57*2d586421SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 58*2d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 59*2d586421SSepherosa Ziehau * documentation and/or other materials provided with the distribution. 60*2d586421SSepherosa Ziehau * 3. All advertising materials mentioning features or use of this software 61*2d586421SSepherosa Ziehau * must display the following acknowledgement: 62*2d586421SSepherosa Ziehau * This product includes software developed by Bill Paul. 63*2d586421SSepherosa Ziehau * 4. Neither the name of the author nor the names of any co-contributors 64*2d586421SSepherosa Ziehau * may be used to endorse or promote products derived from this software 65*2d586421SSepherosa Ziehau * without specific prior written permission. 66*2d586421SSepherosa Ziehau * 67*2d586421SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 68*2d586421SSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 69*2d586421SSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 70*2d586421SSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 71*2d586421SSepherosa Ziehau * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 72*2d586421SSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 73*2d586421SSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 74*2d586421SSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 75*2d586421SSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 76*2d586421SSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 77*2d586421SSepherosa Ziehau * THE POSSIBILITY OF SUCH DAMAGE. 78*2d586421SSepherosa Ziehau */ 79*2d586421SSepherosa Ziehau /*- 80*2d586421SSepherosa Ziehau * Copyright (c) 2003 Nathan L. Binkert <binkertn@umich.edu> 81*2d586421SSepherosa Ziehau * 82*2d586421SSepherosa Ziehau * Permission to use, copy, modify, and distribute this software for any 83*2d586421SSepherosa Ziehau * purpose with or without fee is hereby granted, provided that the above 84*2d586421SSepherosa Ziehau * copyright notice and this permission notice appear in all copies. 85*2d586421SSepherosa Ziehau * 86*2d586421SSepherosa Ziehau * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 87*2d586421SSepherosa Ziehau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 88*2d586421SSepherosa Ziehau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 89*2d586421SSepherosa Ziehau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 90*2d586421SSepherosa Ziehau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 91*2d586421SSepherosa Ziehau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 92*2d586421SSepherosa Ziehau * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 93*2d586421SSepherosa Ziehau */ 94*2d586421SSepherosa Ziehau 95*2d586421SSepherosa Ziehau /* $FreeBSD: src/sys/dev/msk/if_msk.c,v 1.26 2007/12/05 09:41:58 remko Exp $ */ 96*2d586421SSepherosa Ziehau /* $DragonFly: src/sys/dev/netif/msk/if_msk.c,v 1.1 2007/12/26 14:02:36 sephe Exp $ */ 97*2d586421SSepherosa Ziehau 98*2d586421SSepherosa Ziehau /* 99*2d586421SSepherosa Ziehau * Device driver for the Marvell Yukon II Ethernet controller. 100*2d586421SSepherosa Ziehau * Due to lack of documentation, this driver is based on the code from 101*2d586421SSepherosa Ziehau * sk(4) and Marvell's myk(4) driver for FreeBSD 5.x. 102*2d586421SSepherosa Ziehau */ 103*2d586421SSepherosa Ziehau 104*2d586421SSepherosa Ziehau #include <sys/param.h> 105*2d586421SSepherosa Ziehau #include <sys/endian.h> 106*2d586421SSepherosa Ziehau #include <sys/kernel.h> 107*2d586421SSepherosa Ziehau #include <sys/bus.h> 108*2d586421SSepherosa Ziehau #include <sys/in_cksum.h> 109*2d586421SSepherosa Ziehau #include <sys/malloc.h> 110*2d586421SSepherosa Ziehau #include <sys/proc.h> 111*2d586421SSepherosa Ziehau #include <sys/rman.h> 112*2d586421SSepherosa Ziehau #include <sys/serialize.h> 113*2d586421SSepherosa Ziehau #include <sys/socket.h> 114*2d586421SSepherosa Ziehau #include <sys/sockio.h> 115*2d586421SSepherosa Ziehau #include <sys/sysctl.h> 116*2d586421SSepherosa Ziehau 117*2d586421SSepherosa Ziehau #include <net/ethernet.h> 118*2d586421SSepherosa Ziehau #include <net/if.h> 119*2d586421SSepherosa Ziehau #include <net/bpf.h> 120*2d586421SSepherosa Ziehau #include <net/if_arp.h> 121*2d586421SSepherosa Ziehau #include <net/if_dl.h> 122*2d586421SSepherosa Ziehau #include <net/if_media.h> 123*2d586421SSepherosa Ziehau #include <net/ifq_var.h> 124*2d586421SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 125*2d586421SSepherosa Ziehau 126*2d586421SSepherosa Ziehau #include <netinet/ip.h> 127*2d586421SSepherosa Ziehau #include <netinet/ip_var.h> 128*2d586421SSepherosa Ziehau 129*2d586421SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 130*2d586421SSepherosa Ziehau 131*2d586421SSepherosa Ziehau #include <bus/pci/pcireg.h> 132*2d586421SSepherosa Ziehau #include <bus/pci/pcivar.h> 133*2d586421SSepherosa Ziehau 134*2d586421SSepherosa Ziehau #include "if_mskreg.h" 135*2d586421SSepherosa Ziehau 136*2d586421SSepherosa Ziehau /* "device miibus" required. See GENERIC if you get errors here. */ 137*2d586421SSepherosa Ziehau #include "miibus_if.h" 138*2d586421SSepherosa Ziehau 139*2d586421SSepherosa Ziehau #define MSK_CSUM_FEATURES (CSUM_TCP | CSUM_UDP) 140*2d586421SSepherosa Ziehau 141*2d586421SSepherosa Ziehau /* 142*2d586421SSepherosa Ziehau * Devices supported by this driver. 143*2d586421SSepherosa Ziehau */ 144*2d586421SSepherosa Ziehau static const struct msk_product { 145*2d586421SSepherosa Ziehau uint16_t msk_vendorid; 146*2d586421SSepherosa Ziehau uint16_t msk_deviceid; 147*2d586421SSepherosa Ziehau const char *msk_name; 148*2d586421SSepherosa Ziehau } msk_products[] = { 149*2d586421SSepherosa Ziehau { VENDORID_SK, DEVICEID_SK_YUKON2, 150*2d586421SSepherosa Ziehau "SK-9Sxx Gigabit Ethernet" }, 151*2d586421SSepherosa Ziehau { VENDORID_SK, DEVICEID_SK_YUKON2_EXPR, 152*2d586421SSepherosa Ziehau "SK-9Exx Gigabit Ethernet"}, 153*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8021CU, 154*2d586421SSepherosa Ziehau "Marvell Yukon 88E8021CU Gigabit Ethernet" }, 155*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8021X, 156*2d586421SSepherosa Ziehau "Marvell Yukon 88E8021 SX/LX Gigabit Ethernet" }, 157*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8022CU, 158*2d586421SSepherosa Ziehau "Marvell Yukon 88E8022CU Gigabit Ethernet" }, 159*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8022X, 160*2d586421SSepherosa Ziehau "Marvell Yukon 88E8022 SX/LX Gigabit Ethernet" }, 161*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8061CU, 162*2d586421SSepherosa Ziehau "Marvell Yukon 88E8061CU Gigabit Ethernet" }, 163*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8061X, 164*2d586421SSepherosa Ziehau "Marvell Yukon 88E8061 SX/LX Gigabit Ethernet" }, 165*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8062CU, 166*2d586421SSepherosa Ziehau "Marvell Yukon 88E8062CU Gigabit Ethernet" }, 167*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8062X, 168*2d586421SSepherosa Ziehau "Marvell Yukon 88E8062 SX/LX Gigabit Ethernet" }, 169*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8035, 170*2d586421SSepherosa Ziehau "Marvell Yukon 88E8035 Gigabit Ethernet" }, 171*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8036, 172*2d586421SSepherosa Ziehau "Marvell Yukon 88E8036 Gigabit Ethernet" }, 173*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8038, 174*2d586421SSepherosa Ziehau "Marvell Yukon 88E8038 Gigabit Ethernet" }, 175*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8039, 176*2d586421SSepherosa Ziehau "Marvell Yukon 88E8039 Gigabit Ethernet" }, 177*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4361, 178*2d586421SSepherosa Ziehau "Marvell Yukon 88E8050 Gigabit Ethernet" }, 179*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4360, 180*2d586421SSepherosa Ziehau "Marvell Yukon 88E8052 Gigabit Ethernet" }, 181*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4362, 182*2d586421SSepherosa Ziehau "Marvell Yukon 88E8053 Gigabit Ethernet" }, 183*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4363, 184*2d586421SSepherosa Ziehau "Marvell Yukon 88E8055 Gigabit Ethernet" }, 185*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4364, 186*2d586421SSepherosa Ziehau "Marvell Yukon 88E8056 Gigabit Ethernet" }, 187*2d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_436A, 188*2d586421SSepherosa Ziehau "Marvell Yukon 88E8058 Gigabit Ethernet" }, 189*2d586421SSepherosa Ziehau { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX, 190*2d586421SSepherosa Ziehau "D-Link 550SX Gigabit Ethernet" }, 191*2d586421SSepherosa Ziehau { VENDORID_DLINK, DEVICEID_DLINK_DGE560T, 192*2d586421SSepherosa Ziehau "D-Link 560T Gigabit Ethernet" }, 193*2d586421SSepherosa Ziehau { 0, 0, NULL } 194*2d586421SSepherosa Ziehau }; 195*2d586421SSepherosa Ziehau 196*2d586421SSepherosa Ziehau static const char *model_name[] = { 197*2d586421SSepherosa Ziehau "Yukon XL", 198*2d586421SSepherosa Ziehau "Yukon EC Ultra", 199*2d586421SSepherosa Ziehau "Yukon Unknown", 200*2d586421SSepherosa Ziehau "Yukon EC", 201*2d586421SSepherosa Ziehau "Yukon FE" 202*2d586421SSepherosa Ziehau }; 203*2d586421SSepherosa Ziehau 204*2d586421SSepherosa Ziehau static int mskc_probe(device_t); 205*2d586421SSepherosa Ziehau static int mskc_attach(device_t); 206*2d586421SSepherosa Ziehau static int mskc_detach(device_t); 207*2d586421SSepherosa Ziehau static int mskc_shutdown(device_t); 208*2d586421SSepherosa Ziehau static int mskc_suspend(device_t); 209*2d586421SSepherosa Ziehau static int mskc_resume(device_t); 210*2d586421SSepherosa Ziehau static void mskc_intr(void *); 211*2d586421SSepherosa Ziehau 212*2d586421SSepherosa Ziehau static void mskc_reset(struct msk_softc *); 213*2d586421SSepherosa Ziehau static void mskc_intr_hwerr(struct msk_softc *); 214*2d586421SSepherosa Ziehau static int mskc_handle_events(struct msk_softc *); 215*2d586421SSepherosa Ziehau static void mskc_phy_power(struct msk_softc *, int); 216*2d586421SSepherosa Ziehau static int mskc_setup_rambuffer(struct msk_softc *); 217*2d586421SSepherosa Ziehau static int mskc_status_dma_alloc(struct msk_softc *); 218*2d586421SSepherosa Ziehau static void mskc_status_dma_free(struct msk_softc *); 219*2d586421SSepherosa Ziehau 220*2d586421SSepherosa Ziehau static int msk_probe(device_t); 221*2d586421SSepherosa Ziehau static int msk_attach(device_t); 222*2d586421SSepherosa Ziehau static int msk_detach(device_t); 223*2d586421SSepherosa Ziehau static int msk_miibus_readreg(device_t, int, int); 224*2d586421SSepherosa Ziehau static int msk_miibus_writereg(device_t, int, int, int); 225*2d586421SSepherosa Ziehau static void msk_miibus_statchg(device_t); 226*2d586421SSepherosa Ziehau 227*2d586421SSepherosa Ziehau static void msk_init(void *); 228*2d586421SSepherosa Ziehau static int msk_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 229*2d586421SSepherosa Ziehau static void msk_start(struct ifnet *); 230*2d586421SSepherosa Ziehau static void msk_watchdog(struct ifnet *); 231*2d586421SSepherosa Ziehau static int msk_mediachange(struct ifnet *); 232*2d586421SSepherosa Ziehau static void msk_mediastatus(struct ifnet *, struct ifmediareq *); 233*2d586421SSepherosa Ziehau 234*2d586421SSepherosa Ziehau static void msk_tick(void *); 235*2d586421SSepherosa Ziehau static void msk_intr_phy(struct msk_if_softc *); 236*2d586421SSepherosa Ziehau static void msk_intr_gmac(struct msk_if_softc *); 237*2d586421SSepherosa Ziehau static __inline void 238*2d586421SSepherosa Ziehau msk_rxput(struct msk_if_softc *); 239*2d586421SSepherosa Ziehau static void msk_handle_hwerr(struct msk_if_softc *, uint32_t); 240*2d586421SSepherosa Ziehau static void msk_rxeof(struct msk_if_softc *, uint32_t, int); 241*2d586421SSepherosa Ziehau static void msk_txeof(struct msk_if_softc *, int); 242*2d586421SSepherosa Ziehau static void msk_set_prefetch(struct msk_softc *, int, bus_addr_t, uint32_t); 243*2d586421SSepherosa Ziehau static void msk_set_rambuffer(struct msk_if_softc *); 244*2d586421SSepherosa Ziehau static void msk_stop(struct msk_if_softc *); 245*2d586421SSepherosa Ziehau 246*2d586421SSepherosa Ziehau static void msk_dmamap_cb(void *, bus_dma_segment_t *, int, int); 247*2d586421SSepherosa Ziehau static void msk_dmamap_mbuf_cb(void *, bus_dma_segment_t *, int, 248*2d586421SSepherosa Ziehau bus_size_t, int); 249*2d586421SSepherosa Ziehau static int msk_txrx_dma_alloc(struct msk_if_softc *); 250*2d586421SSepherosa Ziehau static void msk_txrx_dma_free(struct msk_if_softc *); 251*2d586421SSepherosa Ziehau static int msk_init_rx_ring(struct msk_if_softc *); 252*2d586421SSepherosa Ziehau static void msk_init_tx_ring(struct msk_if_softc *); 253*2d586421SSepherosa Ziehau static __inline void 254*2d586421SSepherosa Ziehau msk_discard_rxbuf(struct msk_if_softc *, int); 255*2d586421SSepherosa Ziehau static int msk_newbuf(struct msk_if_softc *, int); 256*2d586421SSepherosa Ziehau static struct mbuf * 257*2d586421SSepherosa Ziehau msk_defrag(struct mbuf *, int, int); 258*2d586421SSepherosa Ziehau static int msk_encap(struct msk_if_softc *, struct mbuf **); 259*2d586421SSepherosa Ziehau 260*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 261*2d586421SSepherosa Ziehau static int msk_init_jumbo_rx_ring(struct msk_if_softc *); 262*2d586421SSepherosa Ziehau static __inline void msk_discard_jumbo_rxbuf(struct msk_if_softc *, int); 263*2d586421SSepherosa Ziehau static int msk_jumbo_newbuf(struct msk_if_softc *, int); 264*2d586421SSepherosa Ziehau static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, int); 265*2d586421SSepherosa Ziehau static void *msk_jalloc(struct msk_if_softc *); 266*2d586421SSepherosa Ziehau static void msk_jfree(void *, void *); 267*2d586421SSepherosa Ziehau #endif 268*2d586421SSepherosa Ziehau 269*2d586421SSepherosa Ziehau static int msk_phy_readreg(struct msk_if_softc *, int, int); 270*2d586421SSepherosa Ziehau static int msk_phy_writereg(struct msk_if_softc *, int, int, int); 271*2d586421SSepherosa Ziehau 272*2d586421SSepherosa Ziehau static void msk_setmulti(struct msk_if_softc *); 273*2d586421SSepherosa Ziehau static void msk_setvlan(struct msk_if_softc *, struct ifnet *); 274*2d586421SSepherosa Ziehau static void msk_setpromisc(struct msk_if_softc *); 275*2d586421SSepherosa Ziehau 276*2d586421SSepherosa Ziehau #ifdef notyet 277*2d586421SSepherosa Ziehau static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); 278*2d586421SSepherosa Ziehau static int sysctl_hw_msk_proc_limit(SYSCTL_HANDLER_ARGS); 279*2d586421SSepherosa Ziehau #endif 280*2d586421SSepherosa Ziehau 281*2d586421SSepherosa Ziehau static int msk_dmamem_create(device_t, bus_size_t, bus_dma_tag_t *, 282*2d586421SSepherosa Ziehau void **, bus_addr_t *, bus_dmamap_t *); 283*2d586421SSepherosa Ziehau static void msk_dmamem_destroy(bus_dma_tag_t, void *, bus_dmamap_t); 284*2d586421SSepherosa Ziehau 285*2d586421SSepherosa Ziehau static device_method_t mskc_methods[] = { 286*2d586421SSepherosa Ziehau /* Device interface */ 287*2d586421SSepherosa Ziehau DEVMETHOD(device_probe, mskc_probe), 288*2d586421SSepherosa Ziehau DEVMETHOD(device_attach, mskc_attach), 289*2d586421SSepherosa Ziehau DEVMETHOD(device_detach, mskc_detach), 290*2d586421SSepherosa Ziehau DEVMETHOD(device_suspend, mskc_suspend), 291*2d586421SSepherosa Ziehau DEVMETHOD(device_resume, mskc_resume), 292*2d586421SSepherosa Ziehau DEVMETHOD(device_shutdown, mskc_shutdown), 293*2d586421SSepherosa Ziehau 294*2d586421SSepherosa Ziehau /* bus interface */ 295*2d586421SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 296*2d586421SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 297*2d586421SSepherosa Ziehau 298*2d586421SSepherosa Ziehau { NULL, NULL } 299*2d586421SSepherosa Ziehau }; 300*2d586421SSepherosa Ziehau 301*2d586421SSepherosa Ziehau static DEFINE_CLASS_0(mskc, mskc_driver, mskc_methods, sizeof(struct msk_softc)); 302*2d586421SSepherosa Ziehau static devclass_t mskc_devclass; 303*2d586421SSepherosa Ziehau 304*2d586421SSepherosa Ziehau static device_method_t msk_methods[] = { 305*2d586421SSepherosa Ziehau /* Device interface */ 306*2d586421SSepherosa Ziehau DEVMETHOD(device_probe, msk_probe), 307*2d586421SSepherosa Ziehau DEVMETHOD(device_attach, msk_attach), 308*2d586421SSepherosa Ziehau DEVMETHOD(device_detach, msk_detach), 309*2d586421SSepherosa Ziehau DEVMETHOD(device_shutdown, bus_generic_shutdown), 310*2d586421SSepherosa Ziehau 311*2d586421SSepherosa Ziehau /* bus interface */ 312*2d586421SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 313*2d586421SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 314*2d586421SSepherosa Ziehau 315*2d586421SSepherosa Ziehau /* MII interface */ 316*2d586421SSepherosa Ziehau DEVMETHOD(miibus_readreg, msk_miibus_readreg), 317*2d586421SSepherosa Ziehau DEVMETHOD(miibus_writereg, msk_miibus_writereg), 318*2d586421SSepherosa Ziehau DEVMETHOD(miibus_statchg, msk_miibus_statchg), 319*2d586421SSepherosa Ziehau 320*2d586421SSepherosa Ziehau { NULL, NULL } 321*2d586421SSepherosa Ziehau }; 322*2d586421SSepherosa Ziehau 323*2d586421SSepherosa Ziehau static DEFINE_CLASS_0(msk, msk_driver, msk_methods, sizeof(struct msk_if_softc)); 324*2d586421SSepherosa Ziehau static devclass_t msk_devclass; 325*2d586421SSepherosa Ziehau 326*2d586421SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_msk); 327*2d586421SSepherosa Ziehau DRIVER_MODULE(if_msk, pci, mskc_driver, mskc_devclass, 0, 0); 328*2d586421SSepherosa Ziehau DRIVER_MODULE(if_msk, mskc, msk_driver, msk_devclass, 0, 0); 329*2d586421SSepherosa Ziehau DRIVER_MODULE(miibus, msk, miibus_driver, miibus_devclass, 0, 0); 330*2d586421SSepherosa Ziehau 331*2d586421SSepherosa Ziehau static int 332*2d586421SSepherosa Ziehau msk_miibus_readreg(device_t dev, int phy, int reg) 333*2d586421SSepherosa Ziehau { 334*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 335*2d586421SSepherosa Ziehau 336*2d586421SSepherosa Ziehau if (phy != PHY_ADDR_MARV) 337*2d586421SSepherosa Ziehau return (0); 338*2d586421SSepherosa Ziehau 339*2d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 340*2d586421SSepherosa Ziehau 341*2d586421SSepherosa Ziehau return (msk_phy_readreg(sc_if, phy, reg)); 342*2d586421SSepherosa Ziehau } 343*2d586421SSepherosa Ziehau 344*2d586421SSepherosa Ziehau static int 345*2d586421SSepherosa Ziehau msk_phy_readreg(struct msk_if_softc *sc_if, int phy, int reg) 346*2d586421SSepherosa Ziehau { 347*2d586421SSepherosa Ziehau struct msk_softc *sc; 348*2d586421SSepherosa Ziehau int i, val; 349*2d586421SSepherosa Ziehau 350*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 351*2d586421SSepherosa Ziehau 352*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_CTRL, 353*2d586421SSepherosa Ziehau GM_SMI_CT_PHY_AD(phy) | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); 354*2d586421SSepherosa Ziehau 355*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 356*2d586421SSepherosa Ziehau DELAY(1); 357*2d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_CTRL); 358*2d586421SSepherosa Ziehau if ((val & GM_SMI_CT_RD_VAL) != 0) { 359*2d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_DATA); 360*2d586421SSepherosa Ziehau break; 361*2d586421SSepherosa Ziehau } 362*2d586421SSepherosa Ziehau } 363*2d586421SSepherosa Ziehau 364*2d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) { 365*2d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "phy failed to come ready\n"); 366*2d586421SSepherosa Ziehau val = 0; 367*2d586421SSepherosa Ziehau } 368*2d586421SSepherosa Ziehau 369*2d586421SSepherosa Ziehau return (val); 370*2d586421SSepherosa Ziehau } 371*2d586421SSepherosa Ziehau 372*2d586421SSepherosa Ziehau static int 373*2d586421SSepherosa Ziehau msk_miibus_writereg(device_t dev, int phy, int reg, int val) 374*2d586421SSepherosa Ziehau { 375*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 376*2d586421SSepherosa Ziehau 377*2d586421SSepherosa Ziehau if (phy != PHY_ADDR_MARV) 378*2d586421SSepherosa Ziehau return (0); 379*2d586421SSepherosa Ziehau 380*2d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 381*2d586421SSepherosa Ziehau 382*2d586421SSepherosa Ziehau return (msk_phy_writereg(sc_if, phy, reg, val)); 383*2d586421SSepherosa Ziehau } 384*2d586421SSepherosa Ziehau 385*2d586421SSepherosa Ziehau static int 386*2d586421SSepherosa Ziehau msk_phy_writereg(struct msk_if_softc *sc_if, int phy, int reg, int val) 387*2d586421SSepherosa Ziehau { 388*2d586421SSepherosa Ziehau struct msk_softc *sc; 389*2d586421SSepherosa Ziehau int i; 390*2d586421SSepherosa Ziehau 391*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 392*2d586421SSepherosa Ziehau 393*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_DATA, val); 394*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_CTRL, 395*2d586421SSepherosa Ziehau GM_SMI_CT_PHY_AD(phy) | GM_SMI_CT_REG_AD(reg)); 396*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 397*2d586421SSepherosa Ziehau DELAY(1); 398*2d586421SSepherosa Ziehau if ((GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_CTRL) & 399*2d586421SSepherosa Ziehau GM_SMI_CT_BUSY) == 0) 400*2d586421SSepherosa Ziehau break; 401*2d586421SSepherosa Ziehau } 402*2d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 403*2d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "phy write timeout\n"); 404*2d586421SSepherosa Ziehau 405*2d586421SSepherosa Ziehau return (0); 406*2d586421SSepherosa Ziehau } 407*2d586421SSepherosa Ziehau 408*2d586421SSepherosa Ziehau static void 409*2d586421SSepherosa Ziehau msk_miibus_statchg(device_t dev) 410*2d586421SSepherosa Ziehau { 411*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 412*2d586421SSepherosa Ziehau struct msk_softc *sc; 413*2d586421SSepherosa Ziehau struct mii_data *mii; 414*2d586421SSepherosa Ziehau struct ifnet *ifp; 415*2d586421SSepherosa Ziehau uint32_t gmac; 416*2d586421SSepherosa Ziehau 417*2d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 418*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 419*2d586421SSepherosa Ziehau 420*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 421*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 422*2d586421SSepherosa Ziehau 423*2d586421SSepherosa Ziehau if (mii->mii_media_status & IFM_ACTIVE) { 424*2d586421SSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) 425*2d586421SSepherosa Ziehau sc_if->msk_link = 1; 426*2d586421SSepherosa Ziehau } else 427*2d586421SSepherosa Ziehau sc_if->msk_link = 0; 428*2d586421SSepherosa Ziehau 429*2d586421SSepherosa Ziehau if (sc_if->msk_link != 0) { 430*2d586421SSepherosa Ziehau /* Enable Tx FIFO Underrun. */ 431*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK), 432*2d586421SSepherosa Ziehau GM_IS_TX_FF_UR | GM_IS_RX_FF_OR); 433*2d586421SSepherosa Ziehau /* 434*2d586421SSepherosa Ziehau * Because mii(4) notify msk(4) that it detected link status 435*2d586421SSepherosa Ziehau * change, there is no need to enable automatic 436*2d586421SSepherosa Ziehau * speed/flow-control/duplex updates. 437*2d586421SSepherosa Ziehau */ 438*2d586421SSepherosa Ziehau gmac = GM_GPCR_AU_ALL_DIS; 439*2d586421SSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 440*2d586421SSepherosa Ziehau case IFM_1000_SX: 441*2d586421SSepherosa Ziehau case IFM_1000_T: 442*2d586421SSepherosa Ziehau gmac |= GM_GPCR_SPEED_1000; 443*2d586421SSepherosa Ziehau break; 444*2d586421SSepherosa Ziehau case IFM_100_TX: 445*2d586421SSepherosa Ziehau gmac |= GM_GPCR_SPEED_100; 446*2d586421SSepherosa Ziehau break; 447*2d586421SSepherosa Ziehau case IFM_10_T: 448*2d586421SSepherosa Ziehau break; 449*2d586421SSepherosa Ziehau } 450*2d586421SSepherosa Ziehau 451*2d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0) 452*2d586421SSepherosa Ziehau gmac |= GM_GPCR_DUP_FULL; 453*2d586421SSepherosa Ziehau /* Disable Rx flow control. */ 454*2d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) == 0) 455*2d586421SSepherosa Ziehau gmac |= GM_GPCR_FC_RX_DIS; 456*2d586421SSepherosa Ziehau /* Disable Tx flow control. */ 457*2d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) == 0) 458*2d586421SSepherosa Ziehau gmac |= GM_GPCR_FC_TX_DIS; 459*2d586421SSepherosa Ziehau gmac |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; 460*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac); 461*2d586421SSepherosa Ziehau /* Read again to ensure writing. */ 462*2d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 463*2d586421SSepherosa Ziehau 464*2d586421SSepherosa Ziehau gmac = GMC_PAUSE_ON; 465*2d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & 466*2d586421SSepherosa Ziehau (IFM_FLAG0 | IFM_FLAG1)) == 0) 467*2d586421SSepherosa Ziehau gmac = GMC_PAUSE_OFF; 468*2d586421SSepherosa Ziehau /* Diable pause for 10/100 Mbps in half-duplex mode. */ 469*2d586421SSepherosa Ziehau if ((((mii->mii_media_active & IFM_GMASK) & IFM_FDX) == 0) && 470*2d586421SSepherosa Ziehau (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX || 471*2d586421SSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T)) 472*2d586421SSepherosa Ziehau gmac = GMC_PAUSE_OFF; 473*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), gmac); 474*2d586421SSepherosa Ziehau 475*2d586421SSepherosa Ziehau /* Enable PHY interrupt for FIFO underrun/overflow. */ 476*2d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, 477*2d586421SSepherosa Ziehau PHY_MARV_INT_MASK, PHY_M_IS_FIFO_ERROR); 478*2d586421SSepherosa Ziehau } else { 479*2d586421SSepherosa Ziehau /* 480*2d586421SSepherosa Ziehau * Link state changed to down. 481*2d586421SSepherosa Ziehau * Disable PHY interrupts. 482*2d586421SSepherosa Ziehau */ 483*2d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_MASK, 0); 484*2d586421SSepherosa Ziehau /* Disable Rx/Tx MAC. */ 485*2d586421SSepherosa Ziehau gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 486*2d586421SSepherosa Ziehau gmac &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); 487*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac); 488*2d586421SSepherosa Ziehau /* Read again to ensure writing. */ 489*2d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 490*2d586421SSepherosa Ziehau } 491*2d586421SSepherosa Ziehau } 492*2d586421SSepherosa Ziehau 493*2d586421SSepherosa Ziehau static void 494*2d586421SSepherosa Ziehau msk_setmulti(struct msk_if_softc *sc_if) 495*2d586421SSepherosa Ziehau { 496*2d586421SSepherosa Ziehau struct msk_softc *sc; 497*2d586421SSepherosa Ziehau struct ifnet *ifp; 498*2d586421SSepherosa Ziehau struct ifmultiaddr *ifma; 499*2d586421SSepherosa Ziehau uint32_t mchash[2]; 500*2d586421SSepherosa Ziehau uint32_t crc; 501*2d586421SSepherosa Ziehau uint16_t mode; 502*2d586421SSepherosa Ziehau 503*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 504*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 505*2d586421SSepherosa Ziehau 506*2d586421SSepherosa Ziehau bzero(mchash, sizeof(mchash)); 507*2d586421SSepherosa Ziehau mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL); 508*2d586421SSepherosa Ziehau mode |= GM_RXCR_UCF_ENA; 509*2d586421SSepherosa Ziehau if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 510*2d586421SSepherosa Ziehau if ((ifp->if_flags & IFF_PROMISC) != 0) 511*2d586421SSepherosa Ziehau mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 512*2d586421SSepherosa Ziehau else if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 513*2d586421SSepherosa Ziehau mchash[0] = 0xffff; 514*2d586421SSepherosa Ziehau mchash[1] = 0xffff; 515*2d586421SSepherosa Ziehau } 516*2d586421SSepherosa Ziehau } else { 517*2d586421SSepherosa Ziehau LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 518*2d586421SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 519*2d586421SSepherosa Ziehau continue; 520*2d586421SSepherosa Ziehau crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 521*2d586421SSepherosa Ziehau ifma->ifma_addr), ETHER_ADDR_LEN); 522*2d586421SSepherosa Ziehau /* Just want the 6 least significant bits. */ 523*2d586421SSepherosa Ziehau crc &= 0x3f; 524*2d586421SSepherosa Ziehau /* Set the corresponding bit in the hash table. */ 525*2d586421SSepherosa Ziehau mchash[crc >> 5] |= 1 << (crc & 0x1f); 526*2d586421SSepherosa Ziehau } 527*2d586421SSepherosa Ziehau mode |= GM_RXCR_MCF_ENA; 528*2d586421SSepherosa Ziehau } 529*2d586421SSepherosa Ziehau 530*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H1, 531*2d586421SSepherosa Ziehau mchash[0] & 0xffff); 532*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H2, 533*2d586421SSepherosa Ziehau (mchash[0] >> 16) & 0xffff); 534*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H3, 535*2d586421SSepherosa Ziehau mchash[1] & 0xffff); 536*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H4, 537*2d586421SSepherosa Ziehau (mchash[1] >> 16) & 0xffff); 538*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, mode); 539*2d586421SSepherosa Ziehau } 540*2d586421SSepherosa Ziehau 541*2d586421SSepherosa Ziehau static void 542*2d586421SSepherosa Ziehau msk_setvlan(struct msk_if_softc *sc_if, struct ifnet *ifp) 543*2d586421SSepherosa Ziehau { 544*2d586421SSepherosa Ziehau struct msk_softc *sc; 545*2d586421SSepherosa Ziehau 546*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 547*2d586421SSepherosa Ziehau if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 548*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 549*2d586421SSepherosa Ziehau RX_VLAN_STRIP_ON); 550*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 551*2d586421SSepherosa Ziehau TX_VLAN_TAG_ON); 552*2d586421SSepherosa Ziehau } else { 553*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 554*2d586421SSepherosa Ziehau RX_VLAN_STRIP_OFF); 555*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 556*2d586421SSepherosa Ziehau TX_VLAN_TAG_OFF); 557*2d586421SSepherosa Ziehau } 558*2d586421SSepherosa Ziehau } 559*2d586421SSepherosa Ziehau 560*2d586421SSepherosa Ziehau static void 561*2d586421SSepherosa Ziehau msk_setpromisc(struct msk_if_softc *sc_if) 562*2d586421SSepherosa Ziehau { 563*2d586421SSepherosa Ziehau struct msk_softc *sc; 564*2d586421SSepherosa Ziehau struct ifnet *ifp; 565*2d586421SSepherosa Ziehau uint16_t mode; 566*2d586421SSepherosa Ziehau 567*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 568*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 569*2d586421SSepherosa Ziehau 570*2d586421SSepherosa Ziehau mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL); 571*2d586421SSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) 572*2d586421SSepherosa Ziehau mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 573*2d586421SSepherosa Ziehau else 574*2d586421SSepherosa Ziehau mode |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 575*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, mode); 576*2d586421SSepherosa Ziehau } 577*2d586421SSepherosa Ziehau 578*2d586421SSepherosa Ziehau static int 579*2d586421SSepherosa Ziehau msk_init_rx_ring(struct msk_if_softc *sc_if) 580*2d586421SSepherosa Ziehau { 581*2d586421SSepherosa Ziehau struct msk_ring_data *rd; 582*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 583*2d586421SSepherosa Ziehau int i, prod; 584*2d586421SSepherosa Ziehau 585*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_cons = 0; 586*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = 0; 587*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_putwm = MSK_PUT_WM; 588*2d586421SSepherosa Ziehau 589*2d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 590*2d586421SSepherosa Ziehau bzero(rd->msk_rx_ring, sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT); 591*2d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_rx_prod; 592*2d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 593*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[prod]; 594*2d586421SSepherosa Ziehau rxd->rx_m = NULL; 595*2d586421SSepherosa Ziehau rxd->rx_le = &rd->msk_rx_ring[prod]; 596*2d586421SSepherosa Ziehau if (msk_newbuf(sc_if, prod) != 0) 597*2d586421SSepherosa Ziehau return (ENOBUFS); 598*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_RX_RING_CNT); 599*2d586421SSepherosa Ziehau } 600*2d586421SSepherosa Ziehau 601*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_rx_ring_tag, 602*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_ring_map, BUS_DMASYNC_PREWRITE); 603*2d586421SSepherosa Ziehau 604*2d586421SSepherosa Ziehau /* Update prefetch unit. */ 605*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = MSK_RX_RING_CNT - 1; 606*2d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 607*2d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_PUT_IDX_REG), 608*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod); 609*2d586421SSepherosa Ziehau 610*2d586421SSepherosa Ziehau return (0); 611*2d586421SSepherosa Ziehau } 612*2d586421SSepherosa Ziehau 613*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 614*2d586421SSepherosa Ziehau static int 615*2d586421SSepherosa Ziehau msk_init_jumbo_rx_ring(struct msk_if_softc *sc_if) 616*2d586421SSepherosa Ziehau { 617*2d586421SSepherosa Ziehau struct msk_ring_data *rd; 618*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 619*2d586421SSepherosa Ziehau int i, prod; 620*2d586421SSepherosa Ziehau 621*2d586421SSepherosa Ziehau MSK_IF_LOCK_ASSERT(sc_if); 622*2d586421SSepherosa Ziehau 623*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_cons = 0; 624*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = 0; 625*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_putwm = MSK_PUT_WM; 626*2d586421SSepherosa Ziehau 627*2d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 628*2d586421SSepherosa Ziehau bzero(rd->msk_jumbo_rx_ring, 629*2d586421SSepherosa Ziehau sizeof(struct msk_rx_desc) * MSK_JUMBO_RX_RING_CNT); 630*2d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_rx_prod; 631*2d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 632*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[prod]; 633*2d586421SSepherosa Ziehau rxd->rx_m = NULL; 634*2d586421SSepherosa Ziehau rxd->rx_le = &rd->msk_jumbo_rx_ring[prod]; 635*2d586421SSepherosa Ziehau if (msk_jumbo_newbuf(sc_if, prod) != 0) 636*2d586421SSepherosa Ziehau return (ENOBUFS); 637*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_JUMBO_RX_RING_CNT); 638*2d586421SSepherosa Ziehau } 639*2d586421SSepherosa Ziehau 640*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 641*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 642*2d586421SSepherosa Ziehau BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 643*2d586421SSepherosa Ziehau 644*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = MSK_JUMBO_RX_RING_CNT - 1; 645*2d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 646*2d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_PUT_IDX_REG), 647*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod); 648*2d586421SSepherosa Ziehau 649*2d586421SSepherosa Ziehau return (0); 650*2d586421SSepherosa Ziehau } 651*2d586421SSepherosa Ziehau #endif 652*2d586421SSepherosa Ziehau 653*2d586421SSepherosa Ziehau static void 654*2d586421SSepherosa Ziehau msk_init_tx_ring(struct msk_if_softc *sc_if) 655*2d586421SSepherosa Ziehau { 656*2d586421SSepherosa Ziehau struct msk_ring_data *rd; 657*2d586421SSepherosa Ziehau struct msk_txdesc *txd; 658*2d586421SSepherosa Ziehau int i; 659*2d586421SSepherosa Ziehau 660*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod = 0; 661*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cons = 0; 662*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt = 0; 663*2d586421SSepherosa Ziehau 664*2d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 665*2d586421SSepherosa Ziehau bzero(rd->msk_tx_ring, sizeof(struct msk_tx_desc) * MSK_TX_RING_CNT); 666*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 667*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 668*2d586421SSepherosa Ziehau txd->tx_m = NULL; 669*2d586421SSepherosa Ziehau txd->tx_le = &rd->msk_tx_ring[i]; 670*2d586421SSepherosa Ziehau } 671*2d586421SSepherosa Ziehau 672*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_ring_tag, 673*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_ring_map, BUS_DMASYNC_PREWRITE); 674*2d586421SSepherosa Ziehau } 675*2d586421SSepherosa Ziehau 676*2d586421SSepherosa Ziehau static __inline void 677*2d586421SSepherosa Ziehau msk_discard_rxbuf(struct msk_if_softc *sc_if, int idx) 678*2d586421SSepherosa Ziehau { 679*2d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 680*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 681*2d586421SSepherosa Ziehau struct mbuf *m; 682*2d586421SSepherosa Ziehau 683*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[idx]; 684*2d586421SSepherosa Ziehau m = rxd->rx_m; 685*2d586421SSepherosa Ziehau rx_le = rxd->rx_le; 686*2d586421SSepherosa Ziehau rx_le->msk_control = htole32(m->m_len | OP_PACKET | HW_OWNER); 687*2d586421SSepherosa Ziehau } 688*2d586421SSepherosa Ziehau 689*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 690*2d586421SSepherosa Ziehau static __inline void 691*2d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(struct msk_if_softc *sc_if, int idx) 692*2d586421SSepherosa Ziehau { 693*2d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 694*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 695*2d586421SSepherosa Ziehau struct mbuf *m; 696*2d586421SSepherosa Ziehau 697*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[idx]; 698*2d586421SSepherosa Ziehau m = rxd->rx_m; 699*2d586421SSepherosa Ziehau rx_le = rxd->rx_le; 700*2d586421SSepherosa Ziehau rx_le->msk_control = htole32(m->m_len | OP_PACKET | HW_OWNER); 701*2d586421SSepherosa Ziehau } 702*2d586421SSepherosa Ziehau #endif 703*2d586421SSepherosa Ziehau 704*2d586421SSepherosa Ziehau static int 705*2d586421SSepherosa Ziehau msk_newbuf(struct msk_if_softc *sc_if, int idx) 706*2d586421SSepherosa Ziehau { 707*2d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 708*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 709*2d586421SSepherosa Ziehau struct mbuf *m; 710*2d586421SSepherosa Ziehau struct msk_dmamap_arg ctx; 711*2d586421SSepherosa Ziehau bus_dma_segment_t seg; 712*2d586421SSepherosa Ziehau bus_dmamap_t map; 713*2d586421SSepherosa Ziehau 714*2d586421SSepherosa Ziehau m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); 715*2d586421SSepherosa Ziehau if (m == NULL) 716*2d586421SSepherosa Ziehau return (ENOBUFS); 717*2d586421SSepherosa Ziehau 718*2d586421SSepherosa Ziehau m->m_len = m->m_pkthdr.len = MCLBYTES; 719*2d586421SSepherosa Ziehau m_adj(m, ETHER_ALIGN); 720*2d586421SSepherosa Ziehau 721*2d586421SSepherosa Ziehau bzero(&ctx, sizeof(ctx)); 722*2d586421SSepherosa Ziehau ctx.nseg = 1; 723*2d586421SSepherosa Ziehau ctx.segs = &seg; 724*2d586421SSepherosa Ziehau if (bus_dmamap_load_mbuf(sc_if->msk_cdata.msk_rx_tag, 725*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap, m, msk_dmamap_mbuf_cb, &ctx, 726*2d586421SSepherosa Ziehau BUS_DMA_NOWAIT) != 0) { 727*2d586421SSepherosa Ziehau m_freem(m); 728*2d586421SSepherosa Ziehau return (ENOBUFS); 729*2d586421SSepherosa Ziehau } 730*2d586421SSepherosa Ziehau KASSERT(ctx.nseg == 1, 731*2d586421SSepherosa Ziehau ("%s: %d segments returned!", __func__, ctx.nseg)); 732*2d586421SSepherosa Ziehau 733*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[idx]; 734*2d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 735*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_rx_tag, rxd->rx_dmamap, 736*2d586421SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 737*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_rx_tag, rxd->rx_dmamap); 738*2d586421SSepherosa Ziehau } 739*2d586421SSepherosa Ziehau map = rxd->rx_dmamap; 740*2d586421SSepherosa Ziehau rxd->rx_dmamap = sc_if->msk_cdata.msk_rx_sparemap; 741*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap = map; 742*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_rx_tag, rxd->rx_dmamap, 743*2d586421SSepherosa Ziehau BUS_DMASYNC_PREREAD); 744*2d586421SSepherosa Ziehau rxd->rx_m = m; 745*2d586421SSepherosa Ziehau rx_le = rxd->rx_le; 746*2d586421SSepherosa Ziehau rx_le->msk_addr = htole32(MSK_ADDR_LO(seg.ds_addr)); 747*2d586421SSepherosa Ziehau rx_le->msk_control = 748*2d586421SSepherosa Ziehau htole32(seg.ds_len | OP_PACKET | HW_OWNER); 749*2d586421SSepherosa Ziehau 750*2d586421SSepherosa Ziehau return (0); 751*2d586421SSepherosa Ziehau } 752*2d586421SSepherosa Ziehau 753*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 754*2d586421SSepherosa Ziehau static int 755*2d586421SSepherosa Ziehau msk_jumbo_newbuf(struct msk_if_softc *sc_if, int idx) 756*2d586421SSepherosa Ziehau { 757*2d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 758*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 759*2d586421SSepherosa Ziehau struct mbuf *m; 760*2d586421SSepherosa Ziehau bus_dma_segment_t segs[1]; 761*2d586421SSepherosa Ziehau bus_dmamap_t map; 762*2d586421SSepherosa Ziehau int nsegs; 763*2d586421SSepherosa Ziehau void *buf; 764*2d586421SSepherosa Ziehau 765*2d586421SSepherosa Ziehau MGETHDR(m, M_DONTWAIT, MT_DATA); 766*2d586421SSepherosa Ziehau if (m == NULL) 767*2d586421SSepherosa Ziehau return (ENOBUFS); 768*2d586421SSepherosa Ziehau buf = msk_jalloc(sc_if); 769*2d586421SSepherosa Ziehau if (buf == NULL) { 770*2d586421SSepherosa Ziehau m_freem(m); 771*2d586421SSepherosa Ziehau return (ENOBUFS); 772*2d586421SSepherosa Ziehau } 773*2d586421SSepherosa Ziehau /* Attach the buffer to the mbuf. */ 774*2d586421SSepherosa Ziehau MEXTADD(m, buf, MSK_JLEN, msk_jfree, (struct msk_if_softc *)sc_if, 0, 775*2d586421SSepherosa Ziehau EXT_NET_DRV); 776*2d586421SSepherosa Ziehau if ((m->m_flags & M_EXT) == 0) { 777*2d586421SSepherosa Ziehau m_freem(m); 778*2d586421SSepherosa Ziehau return (ENOBUFS); 779*2d586421SSepherosa Ziehau } 780*2d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = MSK_JLEN; 781*2d586421SSepherosa Ziehau m_adj(m, ETHER_ALIGN); 782*2d586421SSepherosa Ziehau 783*2d586421SSepherosa Ziehau if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_jumbo_rx_tag, 784*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap, m, segs, &nsegs, 785*2d586421SSepherosa Ziehau BUS_DMA_NOWAIT) != 0) { 786*2d586421SSepherosa Ziehau m_freem(m); 787*2d586421SSepherosa Ziehau return (ENOBUFS); 788*2d586421SSepherosa Ziehau } 789*2d586421SSepherosa Ziehau KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 790*2d586421SSepherosa Ziehau 791*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[idx]; 792*2d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 793*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, 794*2d586421SSepherosa Ziehau rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 795*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_tag, 796*2d586421SSepherosa Ziehau rxd->rx_dmamap); 797*2d586421SSepherosa Ziehau } 798*2d586421SSepherosa Ziehau map = rxd->rx_dmamap; 799*2d586421SSepherosa Ziehau rxd->rx_dmamap = sc_if->msk_cdata.msk_jumbo_rx_sparemap; 800*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap = map; 801*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, rxd->rx_dmamap, 802*2d586421SSepherosa Ziehau BUS_DMASYNC_PREREAD); 803*2d586421SSepherosa Ziehau rxd->rx_m = m; 804*2d586421SSepherosa Ziehau rx_le = rxd->rx_le; 805*2d586421SSepherosa Ziehau rx_le->msk_addr = htole32(MSK_ADDR_LO(segs[0].ds_addr)); 806*2d586421SSepherosa Ziehau rx_le->msk_control = 807*2d586421SSepherosa Ziehau htole32(segs[0].ds_len | OP_PACKET | HW_OWNER); 808*2d586421SSepherosa Ziehau 809*2d586421SSepherosa Ziehau return (0); 810*2d586421SSepherosa Ziehau } 811*2d586421SSepherosa Ziehau #endif 812*2d586421SSepherosa Ziehau 813*2d586421SSepherosa Ziehau /* 814*2d586421SSepherosa Ziehau * Set media options. 815*2d586421SSepherosa Ziehau */ 816*2d586421SSepherosa Ziehau static int 817*2d586421SSepherosa Ziehau msk_mediachange(struct ifnet *ifp) 818*2d586421SSepherosa Ziehau { 819*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 820*2d586421SSepherosa Ziehau struct mii_data *mii; 821*2d586421SSepherosa Ziehau 822*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 823*2d586421SSepherosa Ziehau mii_mediachg(mii); 824*2d586421SSepherosa Ziehau 825*2d586421SSepherosa Ziehau return (0); 826*2d586421SSepherosa Ziehau } 827*2d586421SSepherosa Ziehau 828*2d586421SSepherosa Ziehau /* 829*2d586421SSepherosa Ziehau * Report current media status. 830*2d586421SSepherosa Ziehau */ 831*2d586421SSepherosa Ziehau static void 832*2d586421SSepherosa Ziehau msk_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 833*2d586421SSepherosa Ziehau { 834*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 835*2d586421SSepherosa Ziehau struct mii_data *mii; 836*2d586421SSepherosa Ziehau 837*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 838*2d586421SSepherosa Ziehau mii_pollstat(mii); 839*2d586421SSepherosa Ziehau 840*2d586421SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 841*2d586421SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 842*2d586421SSepherosa Ziehau } 843*2d586421SSepherosa Ziehau 844*2d586421SSepherosa Ziehau static int 845*2d586421SSepherosa Ziehau msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 846*2d586421SSepherosa Ziehau { 847*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 848*2d586421SSepherosa Ziehau struct ifreq *ifr; 849*2d586421SSepherosa Ziehau struct mii_data *mii; 850*2d586421SSepherosa Ziehau int error, mask; 851*2d586421SSepherosa Ziehau 852*2d586421SSepherosa Ziehau sc_if = ifp->if_softc; 853*2d586421SSepherosa Ziehau ifr = (struct ifreq *)data; 854*2d586421SSepherosa Ziehau error = 0; 855*2d586421SSepherosa Ziehau 856*2d586421SSepherosa Ziehau switch(command) { 857*2d586421SSepherosa Ziehau case SIOCSIFMTU: 858*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 859*2d586421SSepherosa Ziehau if (ifr->ifr_mtu > MSK_JUMBO_MTU || ifr->ifr_mtu < ETHERMIN) { 860*2d586421SSepherosa Ziehau error = EINVAL; 861*2d586421SSepherosa Ziehau break; 862*2d586421SSepherosa Ziehau } 863*2d586421SSepherosa Ziehau if (sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_FE && 864*2d586421SSepherosa Ziehau ifr->ifr_mtu > MSK_MAX_FRAMELEN) { 865*2d586421SSepherosa Ziehau error = EINVAL; 866*2d586421SSepherosa Ziehau break; 867*2d586421SSepherosa Ziehau } 868*2d586421SSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 869*2d586421SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) != 0) 870*2d586421SSepherosa Ziehau msk_init(sc_if); 871*2d586421SSepherosa Ziehau #else 872*2d586421SSepherosa Ziehau error = EOPNOTSUPP; 873*2d586421SSepherosa Ziehau #endif 874*2d586421SSepherosa Ziehau break; 875*2d586421SSepherosa Ziehau 876*2d586421SSepherosa Ziehau case SIOCSIFFLAGS: 877*2d586421SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 878*2d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 879*2d586421SSepherosa Ziehau if (((ifp->if_flags ^ sc_if->msk_if_flags) 880*2d586421SSepherosa Ziehau & IFF_PROMISC) != 0) { 881*2d586421SSepherosa Ziehau msk_setpromisc(sc_if); 882*2d586421SSepherosa Ziehau msk_setmulti(sc_if); 883*2d586421SSepherosa Ziehau } 884*2d586421SSepherosa Ziehau } else { 885*2d586421SSepherosa Ziehau if (sc_if->msk_detach == 0) 886*2d586421SSepherosa Ziehau msk_init(sc_if); 887*2d586421SSepherosa Ziehau } 888*2d586421SSepherosa Ziehau } else { 889*2d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 890*2d586421SSepherosa Ziehau msk_stop(sc_if); 891*2d586421SSepherosa Ziehau } 892*2d586421SSepherosa Ziehau sc_if->msk_if_flags = ifp->if_flags; 893*2d586421SSepherosa Ziehau break; 894*2d586421SSepherosa Ziehau 895*2d586421SSepherosa Ziehau case SIOCADDMULTI: 896*2d586421SSepherosa Ziehau case SIOCDELMULTI: 897*2d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 898*2d586421SSepherosa Ziehau msk_setmulti(sc_if); 899*2d586421SSepherosa Ziehau break; 900*2d586421SSepherosa Ziehau 901*2d586421SSepherosa Ziehau case SIOCGIFMEDIA: 902*2d586421SSepherosa Ziehau case SIOCSIFMEDIA: 903*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 904*2d586421SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 905*2d586421SSepherosa Ziehau break; 906*2d586421SSepherosa Ziehau 907*2d586421SSepherosa Ziehau case SIOCSIFCAP: 908*2d586421SSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 909*2d586421SSepherosa Ziehau if ((mask & IFCAP_TXCSUM) != 0) { 910*2d586421SSepherosa Ziehau ifp->if_capenable ^= IFCAP_TXCSUM; 911*2d586421SSepherosa Ziehau if ((IFCAP_TXCSUM & ifp->if_capenable) != 0 && 912*2d586421SSepherosa Ziehau (IFCAP_TXCSUM & ifp->if_capabilities) != 0) 913*2d586421SSepherosa Ziehau ifp->if_hwassist |= MSK_CSUM_FEATURES; 914*2d586421SSepherosa Ziehau else 915*2d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 916*2d586421SSepherosa Ziehau } 917*2d586421SSepherosa Ziehau #ifdef notyet 918*2d586421SSepherosa Ziehau if ((mask & IFCAP_VLAN_HWTAGGING) != 0) { 919*2d586421SSepherosa Ziehau ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 920*2d586421SSepherosa Ziehau msk_setvlan(sc_if, ifp); 921*2d586421SSepherosa Ziehau } 922*2d586421SSepherosa Ziehau #endif 923*2d586421SSepherosa Ziehau 924*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && 925*2d586421SSepherosa Ziehau sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 926*2d586421SSepherosa Ziehau /* 927*2d586421SSepherosa Ziehau * In Yukon EC Ultra, TSO & checksum offload is not 928*2d586421SSepherosa Ziehau * supported for jumbo frame. 929*2d586421SSepherosa Ziehau */ 930*2d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 931*2d586421SSepherosa Ziehau ifp->if_capenable &= ~IFCAP_TXCSUM; 932*2d586421SSepherosa Ziehau } 933*2d586421SSepherosa Ziehau break; 934*2d586421SSepherosa Ziehau 935*2d586421SSepherosa Ziehau default: 936*2d586421SSepherosa Ziehau error = ether_ioctl(ifp, command, data); 937*2d586421SSepherosa Ziehau break; 938*2d586421SSepherosa Ziehau } 939*2d586421SSepherosa Ziehau 940*2d586421SSepherosa Ziehau return (error); 941*2d586421SSepherosa Ziehau } 942*2d586421SSepherosa Ziehau 943*2d586421SSepherosa Ziehau static int 944*2d586421SSepherosa Ziehau mskc_probe(device_t dev) 945*2d586421SSepherosa Ziehau { 946*2d586421SSepherosa Ziehau const struct msk_product *mp; 947*2d586421SSepherosa Ziehau uint16_t vendor, devid; 948*2d586421SSepherosa Ziehau 949*2d586421SSepherosa Ziehau vendor = pci_get_vendor(dev); 950*2d586421SSepherosa Ziehau devid = pci_get_device(dev); 951*2d586421SSepherosa Ziehau for (mp = msk_products; mp->msk_name != NULL; ++mp) { 952*2d586421SSepherosa Ziehau if (vendor == mp->msk_vendorid && devid == mp->msk_deviceid) { 953*2d586421SSepherosa Ziehau device_set_desc(dev, mp->msk_name); 954*2d586421SSepherosa Ziehau return (0); 955*2d586421SSepherosa Ziehau } 956*2d586421SSepherosa Ziehau } 957*2d586421SSepherosa Ziehau return (ENXIO); 958*2d586421SSepherosa Ziehau } 959*2d586421SSepherosa Ziehau 960*2d586421SSepherosa Ziehau static int 961*2d586421SSepherosa Ziehau mskc_setup_rambuffer(struct msk_softc *sc) 962*2d586421SSepherosa Ziehau { 963*2d586421SSepherosa Ziehau int next; 964*2d586421SSepherosa Ziehau int i; 965*2d586421SSepherosa Ziehau uint8_t val; 966*2d586421SSepherosa Ziehau 967*2d586421SSepherosa Ziehau /* Get adapter SRAM size. */ 968*2d586421SSepherosa Ziehau val = CSR_READ_1(sc, B2_E_0); 969*2d586421SSepherosa Ziehau sc->msk_ramsize = (val == 0) ? 128 : val * 4; 970*2d586421SSepherosa Ziehau if (bootverbose) { 971*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 972*2d586421SSepherosa Ziehau "RAM buffer size : %dKB\n", sc->msk_ramsize); 973*2d586421SSepherosa Ziehau } 974*2d586421SSepherosa Ziehau /* 975*2d586421SSepherosa Ziehau * Give receiver 2/3 of memory and round down to the multiple 976*2d586421SSepherosa Ziehau * of 1024. Tx/Rx RAM buffer size of Yukon II shoud be multiple 977*2d586421SSepherosa Ziehau * of 1024. 978*2d586421SSepherosa Ziehau */ 979*2d586421SSepherosa Ziehau sc->msk_rxqsize = rounddown((sc->msk_ramsize * 1024 * 2) / 3, 1024); 980*2d586421SSepherosa Ziehau sc->msk_txqsize = (sc->msk_ramsize * 1024) - sc->msk_rxqsize; 981*2d586421SSepherosa Ziehau for (i = 0, next = 0; i < sc->msk_num_port; i++) { 982*2d586421SSepherosa Ziehau sc->msk_rxqstart[i] = next; 983*2d586421SSepherosa Ziehau sc->msk_rxqend[i] = next + sc->msk_rxqsize - 1; 984*2d586421SSepherosa Ziehau next = sc->msk_rxqend[i] + 1; 985*2d586421SSepherosa Ziehau sc->msk_txqstart[i] = next; 986*2d586421SSepherosa Ziehau sc->msk_txqend[i] = next + sc->msk_txqsize - 1; 987*2d586421SSepherosa Ziehau next = sc->msk_txqend[i] + 1; 988*2d586421SSepherosa Ziehau if (bootverbose) { 989*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 990*2d586421SSepherosa Ziehau "Port %d : Rx Queue %dKB(0x%08x:0x%08x)\n", i, 991*2d586421SSepherosa Ziehau sc->msk_rxqsize / 1024, sc->msk_rxqstart[i], 992*2d586421SSepherosa Ziehau sc->msk_rxqend[i]); 993*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 994*2d586421SSepherosa Ziehau "Port %d : Tx Queue %dKB(0x%08x:0x%08x)\n", i, 995*2d586421SSepherosa Ziehau sc->msk_txqsize / 1024, sc->msk_txqstart[i], 996*2d586421SSepherosa Ziehau sc->msk_txqend[i]); 997*2d586421SSepherosa Ziehau } 998*2d586421SSepherosa Ziehau } 999*2d586421SSepherosa Ziehau 1000*2d586421SSepherosa Ziehau return (0); 1001*2d586421SSepherosa Ziehau } 1002*2d586421SSepherosa Ziehau 1003*2d586421SSepherosa Ziehau static void 1004*2d586421SSepherosa Ziehau mskc_phy_power(struct msk_softc *sc, int mode) 1005*2d586421SSepherosa Ziehau { 1006*2d586421SSepherosa Ziehau uint32_t val; 1007*2d586421SSepherosa Ziehau int i; 1008*2d586421SSepherosa Ziehau 1009*2d586421SSepherosa Ziehau switch (mode) { 1010*2d586421SSepherosa Ziehau case MSK_PHY_POWERUP: 1011*2d586421SSepherosa Ziehau /* Switch power to VCC (WA for VAUX problem). */ 1012*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B0_POWER_CTRL, 1013*2d586421SSepherosa Ziehau PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); 1014*2d586421SSepherosa Ziehau /* Disable Core Clock Division, set Clock Select to 0. */ 1015*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); 1016*2d586421SSepherosa Ziehau 1017*2d586421SSepherosa Ziehau val = 0; 1018*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 1019*2d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 1020*2d586421SSepherosa Ziehau /* Enable bits are inverted. */ 1021*2d586421SSepherosa Ziehau val = Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | 1022*2d586421SSepherosa Ziehau Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | 1023*2d586421SSepherosa Ziehau Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS; 1024*2d586421SSepherosa Ziehau } 1025*2d586421SSepherosa Ziehau /* 1026*2d586421SSepherosa Ziehau * Enable PCI & Core Clock, enable clock gating for both Links. 1027*2d586421SSepherosa Ziehau */ 1028*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_Y2_CLK_GATE, val); 1029*2d586421SSepherosa Ziehau 1030*2d586421SSepherosa Ziehau val = pci_read_config(sc->msk_dev, PCI_OUR_REG_1, 4); 1031*2d586421SSepherosa Ziehau val &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); 1032*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 1033*2d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 1034*2d586421SSepherosa Ziehau /* Deassert Low Power for 1st PHY. */ 1035*2d586421SSepherosa Ziehau val |= PCI_Y2_PHY1_COMA; 1036*2d586421SSepherosa Ziehau if (sc->msk_num_port > 1) 1037*2d586421SSepherosa Ziehau val |= PCI_Y2_PHY2_COMA; 1038*2d586421SSepherosa Ziehau } else if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 1039*2d586421SSepherosa Ziehau uint32_t our; 1040*2d586421SSepherosa Ziehau 1041*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_ON); 1042*2d586421SSepherosa Ziehau 1043*2d586421SSepherosa Ziehau /* Enable all clocks. */ 1044*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_3, 0, 4); 1045*2d586421SSepherosa Ziehau our = pci_read_config(sc->msk_dev, PCI_OUR_REG_4, 4); 1046*2d586421SSepherosa Ziehau our &= (PCI_FORCE_ASPM_REQUEST|PCI_ASPM_GPHY_LINK_DOWN| 1047*2d586421SSepherosa Ziehau PCI_ASPM_INT_FIFO_EMPTY|PCI_ASPM_CLKRUN_REQUEST); 1048*2d586421SSepherosa Ziehau /* Set all bits to 0 except bits 15..12. */ 1049*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_4, our, 4); 1050*2d586421SSepherosa Ziehau /* Set to default value. */ 1051*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_5, 0, 4); 1052*2d586421SSepherosa Ziehau } 1053*2d586421SSepherosa Ziehau /* Release PHY from PowerDown/COMA mode. */ 1054*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_1, val, 4); 1055*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 1056*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL), 1057*2d586421SSepherosa Ziehau GMLC_RST_SET); 1058*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL), 1059*2d586421SSepherosa Ziehau GMLC_RST_CLR); 1060*2d586421SSepherosa Ziehau } 1061*2d586421SSepherosa Ziehau break; 1062*2d586421SSepherosa Ziehau case MSK_PHY_POWERDOWN: 1063*2d586421SSepherosa Ziehau val = pci_read_config(sc->msk_dev, PCI_OUR_REG_1, 4); 1064*2d586421SSepherosa Ziehau val |= PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD; 1065*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 1066*2d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 1067*2d586421SSepherosa Ziehau val &= ~PCI_Y2_PHY1_COMA; 1068*2d586421SSepherosa Ziehau if (sc->msk_num_port > 1) 1069*2d586421SSepherosa Ziehau val &= ~PCI_Y2_PHY2_COMA; 1070*2d586421SSepherosa Ziehau } 1071*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_1, val, 4); 1072*2d586421SSepherosa Ziehau 1073*2d586421SSepherosa Ziehau val = Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | 1074*2d586421SSepherosa Ziehau Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | 1075*2d586421SSepherosa Ziehau Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS; 1076*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 1077*2d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 1078*2d586421SSepherosa Ziehau /* Enable bits are inverted. */ 1079*2d586421SSepherosa Ziehau val = 0; 1080*2d586421SSepherosa Ziehau } 1081*2d586421SSepherosa Ziehau /* 1082*2d586421SSepherosa Ziehau * Disable PCI & Core Clock, disable clock gating for 1083*2d586421SSepherosa Ziehau * both Links. 1084*2d586421SSepherosa Ziehau */ 1085*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_Y2_CLK_GATE, val); 1086*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B0_POWER_CTRL, 1087*2d586421SSepherosa Ziehau PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); 1088*2d586421SSepherosa Ziehau break; 1089*2d586421SSepherosa Ziehau default: 1090*2d586421SSepherosa Ziehau break; 1091*2d586421SSepherosa Ziehau } 1092*2d586421SSepherosa Ziehau } 1093*2d586421SSepherosa Ziehau 1094*2d586421SSepherosa Ziehau static void 1095*2d586421SSepherosa Ziehau mskc_reset(struct msk_softc *sc) 1096*2d586421SSepherosa Ziehau { 1097*2d586421SSepherosa Ziehau bus_addr_t addr; 1098*2d586421SSepherosa Ziehau uint16_t status; 1099*2d586421SSepherosa Ziehau uint32_t val; 1100*2d586421SSepherosa Ziehau int i; 1101*2d586421SSepherosa Ziehau 1102*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 1103*2d586421SSepherosa Ziehau 1104*2d586421SSepherosa Ziehau /* Disable ASF. */ 1105*2d586421SSepherosa Ziehau if (sc->msk_hw_id < CHIP_ID_YUKON_XL) { 1106*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); 1107*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE); 1108*2d586421SSepherosa Ziehau } 1109*2d586421SSepherosa Ziehau /* 1110*2d586421SSepherosa Ziehau * Since we disabled ASF, S/W reset is required for Power Management. 1111*2d586421SSepherosa Ziehau */ 1112*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 1113*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 1114*2d586421SSepherosa Ziehau 1115*2d586421SSepherosa Ziehau /* Clear all error bits in the PCI status register. */ 1116*2d586421SSepherosa Ziehau status = pci_read_config(sc->msk_dev, PCIR_STATUS, 2); 1117*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 1118*2d586421SSepherosa Ziehau 1119*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_STATUS, status | 1120*2d586421SSepherosa Ziehau PCIM_STATUS_PERR | PCIM_STATUS_SERR | PCIM_STATUS_RMABORT | 1121*2d586421SSepherosa Ziehau PCIM_STATUS_RTABORT | PCIM_STATUS_PERRREPORT, 2); 1122*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_MRST_CLR); 1123*2d586421SSepherosa Ziehau 1124*2d586421SSepherosa Ziehau switch (sc->msk_bustype) { 1125*2d586421SSepherosa Ziehau case MSK_PEX_BUS: 1126*2d586421SSepherosa Ziehau /* Clear all PEX errors. */ 1127*2d586421SSepherosa Ziehau CSR_PCI_WRITE_4(sc, PEX_UNC_ERR_STAT, 0xffffffff); 1128*2d586421SSepherosa Ziehau val = CSR_PCI_READ_4(sc, PEX_UNC_ERR_STAT); 1129*2d586421SSepherosa Ziehau if ((val & PEX_RX_OV) != 0) { 1130*2d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_HW_ERR; 1131*2d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_IS_PCI_EXP; 1132*2d586421SSepherosa Ziehau } 1133*2d586421SSepherosa Ziehau break; 1134*2d586421SSepherosa Ziehau case MSK_PCI_BUS: 1135*2d586421SSepherosa Ziehau case MSK_PCIX_BUS: 1136*2d586421SSepherosa Ziehau /* Set Cache Line Size to 2(8bytes) if configured to 0. */ 1137*2d586421SSepherosa Ziehau val = pci_read_config(sc->msk_dev, PCIR_CACHELNSZ, 1); 1138*2d586421SSepherosa Ziehau if (val == 0) 1139*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_CACHELNSZ, 2, 1); 1140*2d586421SSepherosa Ziehau if (sc->msk_bustype == MSK_PCIX_BUS) { 1141*2d586421SSepherosa Ziehau /* Set Cache Line Size opt. */ 1142*2d586421SSepherosa Ziehau val = pci_read_config(sc->msk_dev, PCI_OUR_REG_1, 4); 1143*2d586421SSepherosa Ziehau val |= PCI_CLS_OPT; 1144*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCI_OUR_REG_1, val, 4); 1145*2d586421SSepherosa Ziehau } 1146*2d586421SSepherosa Ziehau break; 1147*2d586421SSepherosa Ziehau } 1148*2d586421SSepherosa Ziehau /* Set PHY power state. */ 1149*2d586421SSepherosa Ziehau mskc_phy_power(sc, MSK_PHY_POWERUP); 1150*2d586421SSepherosa Ziehau 1151*2d586421SSepherosa Ziehau /* Reset GPHY/GMAC Control */ 1152*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 1153*2d586421SSepherosa Ziehau /* GPHY Control reset. */ 1154*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_SET); 1155*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_CLR); 1156*2d586421SSepherosa Ziehau /* GMAC Control reset. */ 1157*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_SET); 1158*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_CLR); 1159*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_F_LOOPB_OFF); 1160*2d586421SSepherosa Ziehau } 1161*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 1162*2d586421SSepherosa Ziehau 1163*2d586421SSepherosa Ziehau /* LED On. */ 1164*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_LED_STAT_ON); 1165*2d586421SSepherosa Ziehau 1166*2d586421SSepherosa Ziehau /* Clear TWSI IRQ. */ 1167*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B2_I2C_IRQ, I2C_CLR_IRQ); 1168*2d586421SSepherosa Ziehau 1169*2d586421SSepherosa Ziehau /* Turn off hardware timer. */ 1170*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TI_CTRL, TIM_STOP); 1171*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TI_CTRL, TIM_CLR_IRQ); 1172*2d586421SSepherosa Ziehau 1173*2d586421SSepherosa Ziehau /* Turn off descriptor polling. */ 1174*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B28_DPT_CTRL, DPT_STOP); 1175*2d586421SSepherosa Ziehau 1176*2d586421SSepherosa Ziehau /* Turn off time stamps. */ 1177*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_STOP); 1178*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); 1179*2d586421SSepherosa Ziehau 1180*2d586421SSepherosa Ziehau /* Configure timeout values. */ 1181*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 1182*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), RI_RST_SET); 1183*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR); 1184*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1), 1185*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1186*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA1), 1187*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1188*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS1), 1189*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1190*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_R1), 1191*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1192*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA1), 1193*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1194*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS1), 1195*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1196*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_R2), 1197*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1198*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA2), 1199*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1200*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS2), 1201*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1202*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_R2), 1203*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1204*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA2), 1205*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1206*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS2), 1207*2d586421SSepherosa Ziehau MSK_RI_TO_53); 1208*2d586421SSepherosa Ziehau } 1209*2d586421SSepherosa Ziehau 1210*2d586421SSepherosa Ziehau /* Disable all interrupts. */ 1211*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 1212*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 1213*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 1214*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 1215*2d586421SSepherosa Ziehau 1216*2d586421SSepherosa Ziehau /* 1217*2d586421SSepherosa Ziehau * On dual port PCI-X card, there is an problem where status 1218*2d586421SSepherosa Ziehau * can be received out of order due to split transactions. 1219*2d586421SSepherosa Ziehau */ 1220*2d586421SSepherosa Ziehau if (sc->msk_bustype == MSK_PCIX_BUS && sc->msk_num_port > 1) { 1221*2d586421SSepherosa Ziehau uint16_t pcix_cmd; 1222*2d586421SSepherosa Ziehau uint8_t pcix; 1223*2d586421SSepherosa Ziehau 1224*2d586421SSepherosa Ziehau pcix = pci_get_pcixcap_ptr(sc->msk_dev); 1225*2d586421SSepherosa Ziehau 1226*2d586421SSepherosa Ziehau pcix_cmd = pci_read_config(sc->msk_dev, pcix + 2, 2); 1227*2d586421SSepherosa Ziehau /* Clear Max Outstanding Split Transactions. */ 1228*2d586421SSepherosa Ziehau pcix_cmd &= ~0x70; 1229*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 1230*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, pcix + 2, pcix_cmd, 2); 1231*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 1232*2d586421SSepherosa Ziehau } 1233*2d586421SSepherosa Ziehau if (sc->msk_bustype == MSK_PEX_BUS) { 1234*2d586421SSepherosa Ziehau uint16_t v, width; 1235*2d586421SSepherosa Ziehau 1236*2d586421SSepherosa Ziehau v = pci_read_config(sc->msk_dev, PEX_DEV_CTRL, 2); 1237*2d586421SSepherosa Ziehau /* Change Max. Read Request Size to 4096 bytes. */ 1238*2d586421SSepherosa Ziehau v &= ~PEX_DC_MAX_RRS_MSK; 1239*2d586421SSepherosa Ziehau v |= PEX_DC_MAX_RD_RQ_SIZE(5); 1240*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PEX_DEV_CTRL, v, 2); 1241*2d586421SSepherosa Ziehau width = pci_read_config(sc->msk_dev, PEX_LNK_STAT, 2); 1242*2d586421SSepherosa Ziehau width = (width & PEX_LS_LINK_WI_MSK) >> 4; 1243*2d586421SSepherosa Ziehau v = pci_read_config(sc->msk_dev, PEX_LNK_CAP, 2); 1244*2d586421SSepherosa Ziehau v = (v & PEX_LS_LINK_WI_MSK) >> 4; 1245*2d586421SSepherosa Ziehau if (v != width) { 1246*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 1247*2d586421SSepherosa Ziehau "negotiated width of link(x%d) != " 1248*2d586421SSepherosa Ziehau "max. width of link(x%d)\n", width, v); 1249*2d586421SSepherosa Ziehau } 1250*2d586421SSepherosa Ziehau } 1251*2d586421SSepherosa Ziehau 1252*2d586421SSepherosa Ziehau /* Clear status list. */ 1253*2d586421SSepherosa Ziehau bzero(sc->msk_stat_ring, 1254*2d586421SSepherosa Ziehau sizeof(struct msk_stat_desc) * MSK_STAT_RING_CNT); 1255*2d586421SSepherosa Ziehau sc->msk_stat_cons = 0; 1256*2d586421SSepherosa Ziehau bus_dmamap_sync(sc->msk_stat_tag, sc->msk_stat_map, 1257*2d586421SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1258*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_RST_SET); 1259*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_RST_CLR); 1260*2d586421SSepherosa Ziehau /* Set the status list base address. */ 1261*2d586421SSepherosa Ziehau addr = sc->msk_stat_ring_paddr; 1262*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_LIST_ADDR_LO, MSK_ADDR_LO(addr)); 1263*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_LIST_ADDR_HI, MSK_ADDR_HI(addr)); 1264*2d586421SSepherosa Ziehau /* Set the status list last index. */ 1265*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_LAST_IDX, MSK_STAT_RING_CNT - 1); 1266*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC && 1267*2d586421SSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_EC_A1) { 1268*2d586421SSepherosa Ziehau /* WA for dev. #4.3 */ 1269*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_TX_IDX_TH, ST_TXTH_IDX_MASK); 1270*2d586421SSepherosa Ziehau /* WA for dev. #4.18 */ 1271*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_WM, 0x21); 1272*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x07); 1273*2d586421SSepherosa Ziehau } else { 1274*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_TX_IDX_TH, 0x0a); 1275*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_WM, 0x10); 1276*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 1277*2d586421SSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_XL_A0) 1278*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x04); 1279*2d586421SSepherosa Ziehau else 1280*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x10); 1281*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_ISR_TIMER_INI, 0x0190); 1282*2d586421SSepherosa Ziehau } 1283*2d586421SSepherosa Ziehau /* 1284*2d586421SSepherosa Ziehau * Use default value for STAT_ISR_TIMER_INI, STAT_LEV_TIMER_INI. 1285*2d586421SSepherosa Ziehau */ 1286*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_TX_TIMER_INI, MSK_USECS(sc, 1000)); 1287*2d586421SSepherosa Ziehau 1288*2d586421SSepherosa Ziehau /* Enable status unit. */ 1289*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_OP_ON); 1290*2d586421SSepherosa Ziehau 1291*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_TX_TIMER_CTRL, TIM_START); 1292*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_LEV_TIMER_CTRL, TIM_START); 1293*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_ISR_TIMER_CTRL, TIM_START); 1294*2d586421SSepherosa Ziehau } 1295*2d586421SSepherosa Ziehau 1296*2d586421SSepherosa Ziehau static int 1297*2d586421SSepherosa Ziehau msk_probe(device_t dev) 1298*2d586421SSepherosa Ziehau { 1299*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(device_get_parent(dev)); 1300*2d586421SSepherosa Ziehau char desc[100]; 1301*2d586421SSepherosa Ziehau 1302*2d586421SSepherosa Ziehau /* 1303*2d586421SSepherosa Ziehau * Not much to do here. We always know there will be 1304*2d586421SSepherosa Ziehau * at least one GMAC present, and if there are two, 1305*2d586421SSepherosa Ziehau * mskc_attach() will create a second device instance 1306*2d586421SSepherosa Ziehau * for us. 1307*2d586421SSepherosa Ziehau */ 1308*2d586421SSepherosa Ziehau ksnprintf(desc, sizeof(desc), 1309*2d586421SSepherosa Ziehau "Marvell Technology Group Ltd. %s Id 0x%02x Rev 0x%02x", 1310*2d586421SSepherosa Ziehau model_name[sc->msk_hw_id - CHIP_ID_YUKON_XL], sc->msk_hw_id, 1311*2d586421SSepherosa Ziehau sc->msk_hw_rev); 1312*2d586421SSepherosa Ziehau device_set_desc_copy(dev, desc); 1313*2d586421SSepherosa Ziehau 1314*2d586421SSepherosa Ziehau return (0); 1315*2d586421SSepherosa Ziehau } 1316*2d586421SSepherosa Ziehau 1317*2d586421SSepherosa Ziehau static int 1318*2d586421SSepherosa Ziehau msk_attach(device_t dev) 1319*2d586421SSepherosa Ziehau { 1320*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(device_get_parent(dev)); 1321*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 1322*2d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 1323*2d586421SSepherosa Ziehau int i, port, error; 1324*2d586421SSepherosa Ziehau uint8_t eaddr[ETHER_ADDR_LEN]; 1325*2d586421SSepherosa Ziehau 1326*2d586421SSepherosa Ziehau port = *(int *)device_get_ivars(dev); 1327*2d586421SSepherosa Ziehau KKASSERT(port == MSK_PORT_A || port == MSK_PORT_B); 1328*2d586421SSepherosa Ziehau 1329*2d586421SSepherosa Ziehau kfree(device_get_ivars(dev), M_DEVBUF); 1330*2d586421SSepherosa Ziehau device_set_ivars(dev, NULL); 1331*2d586421SSepherosa Ziehau 1332*2d586421SSepherosa Ziehau callout_init(&sc_if->msk_tick_ch); 1333*2d586421SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1334*2d586421SSepherosa Ziehau 1335*2d586421SSepherosa Ziehau sc_if->msk_if_dev = dev; 1336*2d586421SSepherosa Ziehau sc_if->msk_port = port; 1337*2d586421SSepherosa Ziehau sc_if->msk_softc = sc; 1338*2d586421SSepherosa Ziehau sc_if->msk_ifp = ifp; 1339*2d586421SSepherosa Ziehau sc->msk_if[port] = sc_if; 1340*2d586421SSepherosa Ziehau 1341*2d586421SSepherosa Ziehau /* Setup Tx/Rx queue register offsets. */ 1342*2d586421SSepherosa Ziehau if (port == MSK_PORT_A) { 1343*2d586421SSepherosa Ziehau sc_if->msk_txq = Q_XA1; 1344*2d586421SSepherosa Ziehau sc_if->msk_txsq = Q_XS1; 1345*2d586421SSepherosa Ziehau sc_if->msk_rxq = Q_R1; 1346*2d586421SSepherosa Ziehau } else { 1347*2d586421SSepherosa Ziehau sc_if->msk_txq = Q_XA2; 1348*2d586421SSepherosa Ziehau sc_if->msk_txsq = Q_XS2; 1349*2d586421SSepherosa Ziehau sc_if->msk_rxq = Q_R2; 1350*2d586421SSepherosa Ziehau } 1351*2d586421SSepherosa Ziehau 1352*2d586421SSepherosa Ziehau error = msk_txrx_dma_alloc(sc_if); 1353*2d586421SSepherosa Ziehau if (error) 1354*2d586421SSepherosa Ziehau goto fail; 1355*2d586421SSepherosa Ziehau 1356*2d586421SSepherosa Ziehau ifp->if_softc = sc_if; 1357*2d586421SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 1358*2d586421SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1359*2d586421SSepherosa Ziehau ifp->if_init = msk_init; 1360*2d586421SSepherosa Ziehau ifp->if_ioctl = msk_ioctl; 1361*2d586421SSepherosa Ziehau ifp->if_start = msk_start; 1362*2d586421SSepherosa Ziehau ifp->if_watchdog = msk_watchdog; 1363*2d586421SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, MSK_TX_RING_CNT - 1); 1364*2d586421SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 1365*2d586421SSepherosa Ziehau 1366*2d586421SSepherosa Ziehau #ifdef notyet 1367*2d586421SSepherosa Ziehau /* 1368*2d586421SSepherosa Ziehau * IFCAP_RXCSUM capability is intentionally disabled as the hardware 1369*2d586421SSepherosa Ziehau * has serious bug in Rx checksum offload for all Yukon II family 1370*2d586421SSepherosa Ziehau * hardware. It seems there is a workaround to make it work somtimes. 1371*2d586421SSepherosa Ziehau * However, the workaround also have to check OP code sequences to 1372*2d586421SSepherosa Ziehau * verify whether the OP code is correct. Sometimes it should compute 1373*2d586421SSepherosa Ziehau * IP/TCP/UDP checksum in driver in order to verify correctness of 1374*2d586421SSepherosa Ziehau * checksum computed by hardware. If you have to compute checksum 1375*2d586421SSepherosa Ziehau * with software to verify the hardware's checksum why have hardware 1376*2d586421SSepherosa Ziehau * compute the checksum? I think there is no reason to spend time to 1377*2d586421SSepherosa Ziehau * make Rx checksum offload work on Yukon II hardware. 1378*2d586421SSepherosa Ziehau */ 1379*2d586421SSepherosa Ziehau ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_MTU | 1380*2d586421SSepherosa Ziehau IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM; 1381*2d586421SSepherosa Ziehau ifp->if_hwassist = MSK_CSUM_FEATURES; 1382*2d586421SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 1383*2d586421SSepherosa Ziehau #endif 1384*2d586421SSepherosa Ziehau 1385*2d586421SSepherosa Ziehau /* 1386*2d586421SSepherosa Ziehau * Get station address for this interface. Note that 1387*2d586421SSepherosa Ziehau * dual port cards actually come with three station 1388*2d586421SSepherosa Ziehau * addresses: one for each port, plus an extra. The 1389*2d586421SSepherosa Ziehau * extra one is used by the SysKonnect driver software 1390*2d586421SSepherosa Ziehau * as a 'virtual' station address for when both ports 1391*2d586421SSepherosa Ziehau * are operating in failover mode. Currently we don't 1392*2d586421SSepherosa Ziehau * use this extra address. 1393*2d586421SSepherosa Ziehau */ 1394*2d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) 1395*2d586421SSepherosa Ziehau eaddr[i] = CSR_READ_1(sc, B2_MAC_1 + (port * 8) + i); 1396*2d586421SSepherosa Ziehau 1397*2d586421SSepherosa Ziehau sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + EVL_ENCAPLEN; 1398*2d586421SSepherosa Ziehau 1399*2d586421SSepherosa Ziehau /* 1400*2d586421SSepherosa Ziehau * Do miibus setup. 1401*2d586421SSepherosa Ziehau */ 1402*2d586421SSepherosa Ziehau error = mii_phy_probe(dev, &sc_if->msk_miibus, 1403*2d586421SSepherosa Ziehau msk_mediachange, msk_mediastatus); 1404*2d586421SSepherosa Ziehau if (error) { 1405*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "no PHY found!\n"); 1406*2d586421SSepherosa Ziehau goto fail; 1407*2d586421SSepherosa Ziehau } 1408*2d586421SSepherosa Ziehau 1409*2d586421SSepherosa Ziehau /* 1410*2d586421SSepherosa Ziehau * Call MI attach routine. Can't hold locks when calling into ether_*. 1411*2d586421SSepherosa Ziehau */ 1412*2d586421SSepherosa Ziehau ether_ifattach(ifp, eaddr, &sc->msk_serializer); 1413*2d586421SSepherosa Ziehau #if 0 1414*2d586421SSepherosa Ziehau /* 1415*2d586421SSepherosa Ziehau * Tell the upper layer(s) we support long frames. 1416*2d586421SSepherosa Ziehau * Must appear after the call to ether_ifattach() because 1417*2d586421SSepherosa Ziehau * ether_ifattach() sets ifi_hdrlen to the default value. 1418*2d586421SSepherosa Ziehau */ 1419*2d586421SSepherosa Ziehau ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 1420*2d586421SSepherosa Ziehau #endif 1421*2d586421SSepherosa Ziehau 1422*2d586421SSepherosa Ziehau return 0; 1423*2d586421SSepherosa Ziehau fail: 1424*2d586421SSepherosa Ziehau msk_detach(dev); 1425*2d586421SSepherosa Ziehau sc->msk_if[port] = NULL; 1426*2d586421SSepherosa Ziehau return (error); 1427*2d586421SSepherosa Ziehau } 1428*2d586421SSepherosa Ziehau 1429*2d586421SSepherosa Ziehau /* 1430*2d586421SSepherosa Ziehau * Attach the interface. Allocate softc structures, do ifmedia 1431*2d586421SSepherosa Ziehau * setup and ethernet/BPF attach. 1432*2d586421SSepherosa Ziehau */ 1433*2d586421SSepherosa Ziehau static int 1434*2d586421SSepherosa Ziehau mskc_attach(device_t dev) 1435*2d586421SSepherosa Ziehau { 1436*2d586421SSepherosa Ziehau struct msk_softc *sc; 1437*2d586421SSepherosa Ziehau int error, *port; 1438*2d586421SSepherosa Ziehau 1439*2d586421SSepherosa Ziehau sc = device_get_softc(dev); 1440*2d586421SSepherosa Ziehau sc->msk_dev = dev; 1441*2d586421SSepherosa Ziehau lwkt_serialize_init(&sc->msk_serializer); 1442*2d586421SSepherosa Ziehau 1443*2d586421SSepherosa Ziehau #ifndef BURN_BRIDGES 1444*2d586421SSepherosa Ziehau /* 1445*2d586421SSepherosa Ziehau * Handle power management nonsense. 1446*2d586421SSepherosa Ziehau */ 1447*2d586421SSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 1448*2d586421SSepherosa Ziehau uint32_t irq, bar0, bar1; 1449*2d586421SSepherosa Ziehau 1450*2d586421SSepherosa Ziehau /* Save important PCI config data. */ 1451*2d586421SSepherosa Ziehau bar0 = pci_read_config(dev, PCIR_BAR(0), 4); 1452*2d586421SSepherosa Ziehau bar1 = pci_read_config(dev, PCIR_BAR(1), 4); 1453*2d586421SSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 1454*2d586421SSepherosa Ziehau 1455*2d586421SSepherosa Ziehau /* Reset the power state. */ 1456*2d586421SSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 1457*2d586421SSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 1458*2d586421SSepherosa Ziehau 1459*2d586421SSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 1460*2d586421SSepherosa Ziehau 1461*2d586421SSepherosa Ziehau /* Restore PCI config data. */ 1462*2d586421SSepherosa Ziehau pci_write_config(dev, PCIR_BAR(0), bar0, 4); 1463*2d586421SSepherosa Ziehau pci_write_config(dev, PCIR_BAR(1), bar1, 4); 1464*2d586421SSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 1465*2d586421SSepherosa Ziehau } 1466*2d586421SSepherosa Ziehau #endif /* BURN_BRIDGES */ 1467*2d586421SSepherosa Ziehau 1468*2d586421SSepherosa Ziehau /* 1469*2d586421SSepherosa Ziehau * Map control/status registers. 1470*2d586421SSepherosa Ziehau */ 1471*2d586421SSepherosa Ziehau pci_enable_busmaster(dev); 1472*2d586421SSepherosa Ziehau 1473*2d586421SSepherosa Ziehau /* 1474*2d586421SSepherosa Ziehau * Allocate I/O resource 1475*2d586421SSepherosa Ziehau */ 1476*2d586421SSepherosa Ziehau #ifdef MSK_USEIOSPACE 1477*2d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_IOPORT; 1478*2d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(1); 1479*2d586421SSepherosa Ziehau #else 1480*2d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_MEMORY; 1481*2d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(0); 1482*2d586421SSepherosa Ziehau #endif 1483*2d586421SSepherosa Ziehau sc->msk_res = bus_alloc_resource_any(dev, sc->msk_res_type, 1484*2d586421SSepherosa Ziehau &sc->msk_res_rid, RF_ACTIVE); 1485*2d586421SSepherosa Ziehau if (sc->msk_res == NULL) { 1486*2d586421SSepherosa Ziehau if (sc->msk_res_type == SYS_RES_MEMORY) { 1487*2d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_IOPORT; 1488*2d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(1); 1489*2d586421SSepherosa Ziehau } else { 1490*2d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_MEMORY; 1491*2d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(0); 1492*2d586421SSepherosa Ziehau } 1493*2d586421SSepherosa Ziehau sc->msk_res = bus_alloc_resource_any(dev, sc->msk_res_type, 1494*2d586421SSepherosa Ziehau &sc->msk_res_rid, 1495*2d586421SSepherosa Ziehau RF_ACTIVE); 1496*2d586421SSepherosa Ziehau if (sc->msk_res == NULL) { 1497*2d586421SSepherosa Ziehau device_printf(dev, "couldn't allocate %s resources\n", 1498*2d586421SSepherosa Ziehau sc->msk_res_type == SYS_RES_MEMORY ? "memory" : "I/O"); 1499*2d586421SSepherosa Ziehau return (ENXIO); 1500*2d586421SSepherosa Ziehau } 1501*2d586421SSepherosa Ziehau } 1502*2d586421SSepherosa Ziehau sc->msk_res_bt = rman_get_bustag(sc->msk_res); 1503*2d586421SSepherosa Ziehau sc->msk_res_bh = rman_get_bushandle(sc->msk_res); 1504*2d586421SSepherosa Ziehau 1505*2d586421SSepherosa Ziehau /* 1506*2d586421SSepherosa Ziehau * Allocate IRQ 1507*2d586421SSepherosa Ziehau */ 1508*2d586421SSepherosa Ziehau sc->msk_irq_rid = 0; 1509*2d586421SSepherosa Ziehau sc->msk_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 1510*2d586421SSepherosa Ziehau &sc->msk_irq_rid, 1511*2d586421SSepherosa Ziehau RF_SHAREABLE | RF_ACTIVE); 1512*2d586421SSepherosa Ziehau if (sc->msk_irq == NULL) { 1513*2d586421SSepherosa Ziehau device_printf(dev, "couldn't allocate IRQ resources\n"); 1514*2d586421SSepherosa Ziehau error = ENXIO; 1515*2d586421SSepherosa Ziehau goto fail; 1516*2d586421SSepherosa Ziehau } 1517*2d586421SSepherosa Ziehau 1518*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 1519*2d586421SSepherosa Ziehau sc->msk_hw_id = CSR_READ_1(sc, B2_CHIP_ID); 1520*2d586421SSepherosa Ziehau sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f; 1521*2d586421SSepherosa Ziehau /* Bail out if chip is not recognized. */ 1522*2d586421SSepherosa Ziehau if (sc->msk_hw_id < CHIP_ID_YUKON_XL || 1523*2d586421SSepherosa Ziehau sc->msk_hw_id > CHIP_ID_YUKON_FE) { 1524*2d586421SSepherosa Ziehau device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n", 1525*2d586421SSepherosa Ziehau sc->msk_hw_id, sc->msk_hw_rev); 1526*2d586421SSepherosa Ziehau error = ENXIO; 1527*2d586421SSepherosa Ziehau goto fail; 1528*2d586421SSepherosa Ziehau } 1529*2d586421SSepherosa Ziehau 1530*2d586421SSepherosa Ziehau #if 0 1531*2d586421SSepherosa Ziehau SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1532*2d586421SSepherosa Ziehau SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1533*2d586421SSepherosa Ziehau OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW, 1534*2d586421SSepherosa Ziehau &sc->msk_process_limit, 0, sysctl_hw_msk_proc_limit, "I", 1535*2d586421SSepherosa Ziehau "max number of Rx events to process"); 1536*2d586421SSepherosa Ziehau #endif 1537*2d586421SSepherosa Ziehau 1538*2d586421SSepherosa Ziehau sc->msk_process_limit = MSK_PROC_DEFAULT; 1539*2d586421SSepherosa Ziehau 1540*2d586421SSepherosa Ziehau #if 0 1541*2d586421SSepherosa Ziehau error = resource_int_value(device_get_name(dev), device_get_unit(dev), 1542*2d586421SSepherosa Ziehau "process_limit", &sc->msk_process_limit); 1543*2d586421SSepherosa Ziehau if (error == 0) { 1544*2d586421SSepherosa Ziehau if (sc->msk_process_limit < MSK_PROC_MIN || 1545*2d586421SSepherosa Ziehau sc->msk_process_limit > MSK_PROC_MAX) { 1546*2d586421SSepherosa Ziehau device_printf(dev, "process_limit value out of range; " 1547*2d586421SSepherosa Ziehau "using default: %d\n", MSK_PROC_DEFAULT); 1548*2d586421SSepherosa Ziehau sc->msk_process_limit = MSK_PROC_DEFAULT; 1549*2d586421SSepherosa Ziehau } 1550*2d586421SSepherosa Ziehau } 1551*2d586421SSepherosa Ziehau #endif 1552*2d586421SSepherosa Ziehau 1553*2d586421SSepherosa Ziehau /* Soft reset. */ 1554*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 1555*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 1556*2d586421SSepherosa Ziehau sc->msk_pmd = CSR_READ_1(sc, B2_PMD_TYP); 1557*2d586421SSepherosa Ziehau if (sc->msk_pmd == 'L' || sc->msk_pmd == 'S') 1558*2d586421SSepherosa Ziehau sc->msk_coppertype = 0; 1559*2d586421SSepherosa Ziehau else 1560*2d586421SSepherosa Ziehau sc->msk_coppertype = 1; 1561*2d586421SSepherosa Ziehau /* Check number of MACs. */ 1562*2d586421SSepherosa Ziehau sc->msk_num_port = 1; 1563*2d586421SSepherosa Ziehau if ((CSR_READ_1(sc, B2_Y2_HW_RES) & CFG_DUAL_MAC_MSK) == 1564*2d586421SSepherosa Ziehau CFG_DUAL_MAC_MSK) { 1565*2d586421SSepherosa Ziehau if (!(CSR_READ_1(sc, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) 1566*2d586421SSepherosa Ziehau sc->msk_num_port++; 1567*2d586421SSepherosa Ziehau } 1568*2d586421SSepherosa Ziehau 1569*2d586421SSepherosa Ziehau /* Check bus type. */ 1570*2d586421SSepherosa Ziehau if (pci_is_pcie(sc->msk_dev) == 0) 1571*2d586421SSepherosa Ziehau sc->msk_bustype = MSK_PEX_BUS; 1572*2d586421SSepherosa Ziehau else if (pci_is_pcix(sc->msk_dev) == 0) 1573*2d586421SSepherosa Ziehau sc->msk_bustype = MSK_PCIX_BUS; 1574*2d586421SSepherosa Ziehau else 1575*2d586421SSepherosa Ziehau sc->msk_bustype = MSK_PCI_BUS; 1576*2d586421SSepherosa Ziehau 1577*2d586421SSepherosa Ziehau switch (sc->msk_hw_id) { 1578*2d586421SSepherosa Ziehau case CHIP_ID_YUKON_EC: 1579*2d586421SSepherosa Ziehau case CHIP_ID_YUKON_EC_U: 1580*2d586421SSepherosa Ziehau sc->msk_clock = 125; /* 125 Mhz */ 1581*2d586421SSepherosa Ziehau break; 1582*2d586421SSepherosa Ziehau case CHIP_ID_YUKON_FE: 1583*2d586421SSepherosa Ziehau sc->msk_clock = 100; /* 100 Mhz */ 1584*2d586421SSepherosa Ziehau break; 1585*2d586421SSepherosa Ziehau case CHIP_ID_YUKON_XL: 1586*2d586421SSepherosa Ziehau sc->msk_clock = 156; /* 156 Mhz */ 1587*2d586421SSepherosa Ziehau break; 1588*2d586421SSepherosa Ziehau default: 1589*2d586421SSepherosa Ziehau sc->msk_clock = 156; /* 156 Mhz */ 1590*2d586421SSepherosa Ziehau break; 1591*2d586421SSepherosa Ziehau } 1592*2d586421SSepherosa Ziehau 1593*2d586421SSepherosa Ziehau error = mskc_status_dma_alloc(sc); 1594*2d586421SSepherosa Ziehau if (error) 1595*2d586421SSepherosa Ziehau goto fail; 1596*2d586421SSepherosa Ziehau 1597*2d586421SSepherosa Ziehau /* Set base interrupt mask. */ 1598*2d586421SSepherosa Ziehau sc->msk_intrmask = Y2_IS_HW_ERR | Y2_IS_STAT_BMU; 1599*2d586421SSepherosa Ziehau sc->msk_intrhwemask = Y2_IS_TIST_OV | Y2_IS_MST_ERR | 1600*2d586421SSepherosa Ziehau Y2_IS_IRQ_STAT | Y2_IS_PCI_EXP | Y2_IS_PCI_NEXP; 1601*2d586421SSepherosa Ziehau 1602*2d586421SSepherosa Ziehau /* Reset the adapter. */ 1603*2d586421SSepherosa Ziehau mskc_reset(sc); 1604*2d586421SSepherosa Ziehau 1605*2d586421SSepherosa Ziehau error = mskc_setup_rambuffer(sc); 1606*2d586421SSepherosa Ziehau if (error) 1607*2d586421SSepherosa Ziehau goto fail; 1608*2d586421SSepherosa Ziehau 1609*2d586421SSepherosa Ziehau sc->msk_devs[MSK_PORT_A] = device_add_child(dev, "msk", -1); 1610*2d586421SSepherosa Ziehau if (sc->msk_devs[MSK_PORT_A] == NULL) { 1611*2d586421SSepherosa Ziehau device_printf(dev, "failed to add child for PORT_A\n"); 1612*2d586421SSepherosa Ziehau error = ENXIO; 1613*2d586421SSepherosa Ziehau goto fail; 1614*2d586421SSepherosa Ziehau } 1615*2d586421SSepherosa Ziehau port = kmalloc(sizeof(*port), M_DEVBUF, M_WAITOK); 1616*2d586421SSepherosa Ziehau *port = MSK_PORT_A; 1617*2d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[MSK_PORT_A], port); 1618*2d586421SSepherosa Ziehau 1619*2d586421SSepherosa Ziehau if (sc->msk_num_port > 1) { 1620*2d586421SSepherosa Ziehau sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1); 1621*2d586421SSepherosa Ziehau if (sc->msk_devs[MSK_PORT_B] == NULL) { 1622*2d586421SSepherosa Ziehau device_printf(dev, "failed to add child for PORT_B\n"); 1623*2d586421SSepherosa Ziehau error = ENXIO; 1624*2d586421SSepherosa Ziehau goto fail; 1625*2d586421SSepherosa Ziehau } 1626*2d586421SSepherosa Ziehau port = kmalloc(sizeof(*port), M_DEVBUF, M_WAITOK); 1627*2d586421SSepherosa Ziehau *port = MSK_PORT_B; 1628*2d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[MSK_PORT_B], port); 1629*2d586421SSepherosa Ziehau } 1630*2d586421SSepherosa Ziehau 1631*2d586421SSepherosa Ziehau bus_generic_attach(dev); 1632*2d586421SSepherosa Ziehau 1633*2d586421SSepherosa Ziehau error = bus_setup_intr(dev, sc->msk_irq, INTR_MPSAFE, 1634*2d586421SSepherosa Ziehau mskc_intr, sc, &sc->msk_intrhand, 1635*2d586421SSepherosa Ziehau &sc->msk_serializer); 1636*2d586421SSepherosa Ziehau if (error) { 1637*2d586421SSepherosa Ziehau device_printf(dev, "couldn't set up interrupt handler\n"); 1638*2d586421SSepherosa Ziehau goto fail; 1639*2d586421SSepherosa Ziehau } 1640*2d586421SSepherosa Ziehau return 0; 1641*2d586421SSepherosa Ziehau fail: 1642*2d586421SSepherosa Ziehau mskc_detach(dev); 1643*2d586421SSepherosa Ziehau return (error); 1644*2d586421SSepherosa Ziehau } 1645*2d586421SSepherosa Ziehau 1646*2d586421SSepherosa Ziehau /* 1647*2d586421SSepherosa Ziehau * Shutdown hardware and free up resources. This can be called any 1648*2d586421SSepherosa Ziehau * time after the mutex has been initialized. It is called in both 1649*2d586421SSepherosa Ziehau * the error case in attach and the normal detach case so it needs 1650*2d586421SSepherosa Ziehau * to be careful about only freeing resources that have actually been 1651*2d586421SSepherosa Ziehau * allocated. 1652*2d586421SSepherosa Ziehau */ 1653*2d586421SSepherosa Ziehau static int 1654*2d586421SSepherosa Ziehau msk_detach(device_t dev) 1655*2d586421SSepherosa Ziehau { 1656*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 1657*2d586421SSepherosa Ziehau 1658*2d586421SSepherosa Ziehau if (device_is_attached(dev)) { 1659*2d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 1660*2d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 1661*2d586421SSepherosa Ziehau 1662*2d586421SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 1663*2d586421SSepherosa Ziehau 1664*2d586421SSepherosa Ziehau if (sc->msk_intrhand != NULL) { 1665*2d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_A] != NULL) 1666*2d586421SSepherosa Ziehau msk_stop(sc->msk_if[MSK_PORT_A]); 1667*2d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_B] != NULL) 1668*2d586421SSepherosa Ziehau msk_stop(sc->msk_if[MSK_PORT_B]); 1669*2d586421SSepherosa Ziehau 1670*2d586421SSepherosa Ziehau bus_teardown_intr(sc->msk_dev, sc->msk_irq, 1671*2d586421SSepherosa Ziehau sc->msk_intrhand); 1672*2d586421SSepherosa Ziehau sc->msk_intrhand = NULL; 1673*2d586421SSepherosa Ziehau } 1674*2d586421SSepherosa Ziehau 1675*2d586421SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 1676*2d586421SSepherosa Ziehau 1677*2d586421SSepherosa Ziehau ether_ifdetach(ifp); 1678*2d586421SSepherosa Ziehau } 1679*2d586421SSepherosa Ziehau 1680*2d586421SSepherosa Ziehau if (sc_if->msk_miibus != NULL) 1681*2d586421SSepherosa Ziehau device_delete_child(dev, sc_if->msk_miibus); 1682*2d586421SSepherosa Ziehau 1683*2d586421SSepherosa Ziehau msk_txrx_dma_free(sc_if); 1684*2d586421SSepherosa Ziehau return (0); 1685*2d586421SSepherosa Ziehau } 1686*2d586421SSepherosa Ziehau 1687*2d586421SSepherosa Ziehau static int 1688*2d586421SSepherosa Ziehau mskc_detach(device_t dev) 1689*2d586421SSepherosa Ziehau { 1690*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 1691*2d586421SSepherosa Ziehau int *port, i; 1692*2d586421SSepherosa Ziehau 1693*2d586421SSepherosa Ziehau #ifdef INVARIANTS 1694*2d586421SSepherosa Ziehau if (device_is_attached(dev)) { 1695*2d586421SSepherosa Ziehau KASSERT(sc->msk_intrhand == NULL, 1696*2d586421SSepherosa Ziehau ("intr is not torn down yet\n")); 1697*2d586421SSepherosa Ziehau } 1698*2d586421SSepherosa Ziehau #endif 1699*2d586421SSepherosa Ziehau 1700*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; ++i) { 1701*2d586421SSepherosa Ziehau if (sc->msk_devs[i] != NULL) { 1702*2d586421SSepherosa Ziehau port = device_get_ivars(sc->msk_devs[i]); 1703*2d586421SSepherosa Ziehau if (port != NULL) { 1704*2d586421SSepherosa Ziehau kfree(port, M_DEVBUF); 1705*2d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[i], NULL); 1706*2d586421SSepherosa Ziehau } 1707*2d586421SSepherosa Ziehau device_delete_child(dev, sc->msk_devs[i]); 1708*2d586421SSepherosa Ziehau } 1709*2d586421SSepherosa Ziehau } 1710*2d586421SSepherosa Ziehau 1711*2d586421SSepherosa Ziehau /* Disable all interrupts. */ 1712*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 1713*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 1714*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 1715*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 1716*2d586421SSepherosa Ziehau 1717*2d586421SSepherosa Ziehau /* LED Off. */ 1718*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_LED_STAT_OFF); 1719*2d586421SSepherosa Ziehau 1720*2d586421SSepherosa Ziehau /* Put hardware reset. */ 1721*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 1722*2d586421SSepherosa Ziehau 1723*2d586421SSepherosa Ziehau mskc_status_dma_free(sc); 1724*2d586421SSepherosa Ziehau 1725*2d586421SSepherosa Ziehau if (sc->msk_irq != NULL) { 1726*2d586421SSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->msk_irq_rid, 1727*2d586421SSepherosa Ziehau sc->msk_irq); 1728*2d586421SSepherosa Ziehau } 1729*2d586421SSepherosa Ziehau if (sc->msk_res != NULL) { 1730*2d586421SSepherosa Ziehau bus_release_resource(dev, sc->msk_res_type, sc->msk_res_rid, 1731*2d586421SSepherosa Ziehau sc->msk_res); 1732*2d586421SSepherosa Ziehau } 1733*2d586421SSepherosa Ziehau 1734*2d586421SSepherosa Ziehau return (0); 1735*2d586421SSepherosa Ziehau } 1736*2d586421SSepherosa Ziehau 1737*2d586421SSepherosa Ziehau static void 1738*2d586421SSepherosa Ziehau msk_dmamap_mbuf_cb(void *arg, bus_dma_segment_t *segs, int nseg, 1739*2d586421SSepherosa Ziehau bus_size_t mapsz __unused, int error) 1740*2d586421SSepherosa Ziehau { 1741*2d586421SSepherosa Ziehau struct msk_dmamap_arg *ctx = arg; 1742*2d586421SSepherosa Ziehau int i; 1743*2d586421SSepherosa Ziehau 1744*2d586421SSepherosa Ziehau if (error) 1745*2d586421SSepherosa Ziehau return; 1746*2d586421SSepherosa Ziehau 1747*2d586421SSepherosa Ziehau if (ctx->nseg < nseg) { 1748*2d586421SSepherosa Ziehau ctx->nseg = 0; 1749*2d586421SSepherosa Ziehau return; 1750*2d586421SSepherosa Ziehau } 1751*2d586421SSepherosa Ziehau 1752*2d586421SSepherosa Ziehau ctx->nseg = nseg; 1753*2d586421SSepherosa Ziehau for (i = 0; i < ctx->nseg; ++i) 1754*2d586421SSepherosa Ziehau ctx->segs[i] = segs[i]; 1755*2d586421SSepherosa Ziehau } 1756*2d586421SSepherosa Ziehau 1757*2d586421SSepherosa Ziehau static void 1758*2d586421SSepherosa Ziehau msk_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1759*2d586421SSepherosa Ziehau { 1760*2d586421SSepherosa Ziehau struct msk_dmamap_arg *ctx = arg; 1761*2d586421SSepherosa Ziehau int i; 1762*2d586421SSepherosa Ziehau 1763*2d586421SSepherosa Ziehau if (error) 1764*2d586421SSepherosa Ziehau return; 1765*2d586421SSepherosa Ziehau 1766*2d586421SSepherosa Ziehau KKASSERT(nseg <= ctx->nseg); 1767*2d586421SSepherosa Ziehau 1768*2d586421SSepherosa Ziehau ctx->nseg = nseg; 1769*2d586421SSepherosa Ziehau for (i = 0; i < ctx->nseg; ++i) 1770*2d586421SSepherosa Ziehau ctx->segs[i] = segs[i]; 1771*2d586421SSepherosa Ziehau } 1772*2d586421SSepherosa Ziehau 1773*2d586421SSepherosa Ziehau /* Create status DMA region. */ 1774*2d586421SSepherosa Ziehau static int 1775*2d586421SSepherosa Ziehau mskc_status_dma_alloc(struct msk_softc *sc) 1776*2d586421SSepherosa Ziehau { 1777*2d586421SSepherosa Ziehau struct msk_dmamap_arg ctx; 1778*2d586421SSepherosa Ziehau bus_dma_segment_t seg; 1779*2d586421SSepherosa Ziehau int error; 1780*2d586421SSepherosa Ziehau 1781*2d586421SSepherosa Ziehau error = bus_dma_tag_create( 1782*2d586421SSepherosa Ziehau NULL, /* XXX parent */ 1783*2d586421SSepherosa Ziehau MSK_STAT_ALIGN, 0, /* alignment, boundary */ 1784*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 1785*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 1786*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 1787*2d586421SSepherosa Ziehau MSK_STAT_RING_SZ, /* maxsize */ 1788*2d586421SSepherosa Ziehau 1, /* nsegments */ 1789*2d586421SSepherosa Ziehau MSK_STAT_RING_SZ, /* maxsegsize */ 1790*2d586421SSepherosa Ziehau 0, /* flags */ 1791*2d586421SSepherosa Ziehau &sc->msk_stat_tag); 1792*2d586421SSepherosa Ziehau if (error) { 1793*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 1794*2d586421SSepherosa Ziehau "failed to create status DMA tag\n"); 1795*2d586421SSepherosa Ziehau return (error); 1796*2d586421SSepherosa Ziehau } 1797*2d586421SSepherosa Ziehau 1798*2d586421SSepherosa Ziehau /* Allocate DMA'able memory and load the DMA map for status ring. */ 1799*2d586421SSepherosa Ziehau error = bus_dmamem_alloc(sc->msk_stat_tag, 1800*2d586421SSepherosa Ziehau (void **)&sc->msk_stat_ring, 1801*2d586421SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO, 1802*2d586421SSepherosa Ziehau &sc->msk_stat_map); 1803*2d586421SSepherosa Ziehau if (error) { 1804*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 1805*2d586421SSepherosa Ziehau "failed to allocate DMA'able memory for status ring\n"); 1806*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc->msk_stat_tag); 1807*2d586421SSepherosa Ziehau sc->msk_stat_tag = NULL; 1808*2d586421SSepherosa Ziehau return (error); 1809*2d586421SSepherosa Ziehau } 1810*2d586421SSepherosa Ziehau 1811*2d586421SSepherosa Ziehau bzero(&ctx, sizeof(ctx)); 1812*2d586421SSepherosa Ziehau ctx.nseg = 1; 1813*2d586421SSepherosa Ziehau ctx.segs = &seg; 1814*2d586421SSepherosa Ziehau error = bus_dmamap_load(sc->msk_stat_tag, sc->msk_stat_map, 1815*2d586421SSepherosa Ziehau sc->msk_stat_ring, MSK_STAT_RING_SZ, 1816*2d586421SSepherosa Ziehau msk_dmamap_cb, &ctx, 0); 1817*2d586421SSepherosa Ziehau if (error) { 1818*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 1819*2d586421SSepherosa Ziehau "failed to load DMA'able memory for status ring\n"); 1820*2d586421SSepherosa Ziehau bus_dmamem_free(sc->msk_stat_tag, sc->msk_stat_ring, 1821*2d586421SSepherosa Ziehau sc->msk_stat_map); 1822*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc->msk_stat_tag); 1823*2d586421SSepherosa Ziehau sc->msk_stat_tag = NULL; 1824*2d586421SSepherosa Ziehau return (error); 1825*2d586421SSepherosa Ziehau } 1826*2d586421SSepherosa Ziehau sc->msk_stat_ring_paddr = seg.ds_addr; 1827*2d586421SSepherosa Ziehau 1828*2d586421SSepherosa Ziehau return (0); 1829*2d586421SSepherosa Ziehau } 1830*2d586421SSepherosa Ziehau 1831*2d586421SSepherosa Ziehau static void 1832*2d586421SSepherosa Ziehau mskc_status_dma_free(struct msk_softc *sc) 1833*2d586421SSepherosa Ziehau { 1834*2d586421SSepherosa Ziehau /* Destroy status block. */ 1835*2d586421SSepherosa Ziehau if (sc->msk_stat_tag) { 1836*2d586421SSepherosa Ziehau bus_dmamap_unload(sc->msk_stat_tag, sc->msk_stat_map); 1837*2d586421SSepherosa Ziehau bus_dmamem_free(sc->msk_stat_tag, sc->msk_stat_ring, 1838*2d586421SSepherosa Ziehau sc->msk_stat_map); 1839*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc->msk_stat_tag); 1840*2d586421SSepherosa Ziehau sc->msk_stat_tag = NULL; 1841*2d586421SSepherosa Ziehau } 1842*2d586421SSepherosa Ziehau } 1843*2d586421SSepherosa Ziehau 1844*2d586421SSepherosa Ziehau static int 1845*2d586421SSepherosa Ziehau msk_txrx_dma_alloc(struct msk_if_softc *sc_if) 1846*2d586421SSepherosa Ziehau { 1847*2d586421SSepherosa Ziehau int error, i, j; 1848*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 1849*2d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 1850*2d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 1851*2d586421SSepherosa Ziehau uint8_t *ptr; 1852*2d586421SSepherosa Ziehau #endif 1853*2d586421SSepherosa Ziehau 1854*2d586421SSepherosa Ziehau /* Create parent DMA tag. */ 1855*2d586421SSepherosa Ziehau /* 1856*2d586421SSepherosa Ziehau * XXX 1857*2d586421SSepherosa Ziehau * It seems that Yukon II supports full 64bits DMA operations. But 1858*2d586421SSepherosa Ziehau * it needs two descriptors(list elements) for 64bits DMA operations. 1859*2d586421SSepherosa Ziehau * Since we don't know what DMA address mappings(32bits or 64bits) 1860*2d586421SSepherosa Ziehau * would be used in advance for each mbufs, we limits its DMA space 1861*2d586421SSepherosa Ziehau * to be in range of 32bits address space. Otherwise, we should check 1862*2d586421SSepherosa Ziehau * what DMA address is used and chain another descriptor for the 1863*2d586421SSepherosa Ziehau * 64bits DMA operation. This also means descriptor ring size is 1864*2d586421SSepherosa Ziehau * variable. Limiting DMA address to be in 32bit address space greatly 1865*2d586421SSepherosa Ziehau * simplyfies descriptor handling and possibly would increase 1866*2d586421SSepherosa Ziehau * performance a bit due to efficient handling of descriptors. 1867*2d586421SSepherosa Ziehau * Apart from harassing checksum offloading mechanisms, it seems 1868*2d586421SSepherosa Ziehau * it's really bad idea to use a seperate descriptor for 64bit 1869*2d586421SSepherosa Ziehau * DMA operation to save small descriptor memory. Anyway, I've 1870*2d586421SSepherosa Ziehau * never seen these exotic scheme on ethernet interface hardware. 1871*2d586421SSepherosa Ziehau */ 1872*2d586421SSepherosa Ziehau error = bus_dma_tag_create( 1873*2d586421SSepherosa Ziehau NULL, /* parent */ 1874*2d586421SSepherosa Ziehau 1, 0, /* alignment, boundary */ 1875*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1876*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 1877*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 1878*2d586421SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1879*2d586421SSepherosa Ziehau 0, /* nsegments */ 1880*2d586421SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1881*2d586421SSepherosa Ziehau 0, /* flags */ 1882*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_parent_tag); 1883*2d586421SSepherosa Ziehau if (error) { 1884*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1885*2d586421SSepherosa Ziehau "failed to create parent DMA tag\n"); 1886*2d586421SSepherosa Ziehau return error; 1887*2d586421SSepherosa Ziehau } 1888*2d586421SSepherosa Ziehau 1889*2d586421SSepherosa Ziehau /* Create DMA stuffs for Tx ring. */ 1890*2d586421SSepherosa Ziehau error = msk_dmamem_create(sc_if->msk_if_dev, MSK_TX_RING_SZ, 1891*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_ring_tag, 1892*2d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_tx_ring, 1893*2d586421SSepherosa Ziehau &sc_if->msk_rdata.msk_tx_ring_paddr, 1894*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_ring_map); 1895*2d586421SSepherosa Ziehau if (error) { 1896*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1897*2d586421SSepherosa Ziehau "failed to create TX ring DMA stuffs\n"); 1898*2d586421SSepherosa Ziehau return error; 1899*2d586421SSepherosa Ziehau } 1900*2d586421SSepherosa Ziehau 1901*2d586421SSepherosa Ziehau /* Create DMA stuffs for Rx ring. */ 1902*2d586421SSepherosa Ziehau error = msk_dmamem_create(sc_if->msk_if_dev, MSK_RX_RING_SZ, 1903*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_ring_tag, 1904*2d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_rx_ring, 1905*2d586421SSepherosa Ziehau &sc_if->msk_rdata.msk_rx_ring_paddr, 1906*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_ring_map); 1907*2d586421SSepherosa Ziehau if (error) { 1908*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1909*2d586421SSepherosa Ziehau "failed to create RX ring DMA stuffs\n"); 1910*2d586421SSepherosa Ziehau return error; 1911*2d586421SSepherosa Ziehau } 1912*2d586421SSepherosa Ziehau 1913*2d586421SSepherosa Ziehau /* Create tag for Tx buffers. */ 1914*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 1915*2d586421SSepherosa Ziehau 1, 0, /* alignment, boundary */ 1916*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 1917*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 1918*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 1919*2d586421SSepherosa Ziehau MSK_TSO_MAXSIZE, /* maxsize */ 1920*2d586421SSepherosa Ziehau MSK_MAXTXSEGS, /* nsegments */ 1921*2d586421SSepherosa Ziehau MSK_TSO_MAXSGSIZE, /* maxsegsize */ 1922*2d586421SSepherosa Ziehau 0, /* flags */ 1923*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_tag); 1924*2d586421SSepherosa Ziehau if (error) { 1925*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1926*2d586421SSepherosa Ziehau "failed to create Tx DMA tag\n"); 1927*2d586421SSepherosa Ziehau return error; 1928*2d586421SSepherosa Ziehau } 1929*2d586421SSepherosa Ziehau 1930*2d586421SSepherosa Ziehau /* Create DMA maps for Tx buffers. */ 1931*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 1932*2d586421SSepherosa Ziehau struct msk_txdesc *txd = &sc_if->msk_cdata.msk_txdesc[i]; 1933*2d586421SSepherosa Ziehau 1934*2d586421SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_tx_tag, 0, 1935*2d586421SSepherosa Ziehau &txd->tx_dmamap); 1936*2d586421SSepherosa Ziehau if (error) { 1937*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1938*2d586421SSepherosa Ziehau "failed to create %dth Tx dmamap\n", i); 1939*2d586421SSepherosa Ziehau 1940*2d586421SSepherosa Ziehau for (j = 0; j < i; ++j) { 1941*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[j]; 1942*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_tx_tag, 1943*2d586421SSepherosa Ziehau txd->tx_dmamap); 1944*2d586421SSepherosa Ziehau } 1945*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_tx_tag); 1946*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_tag = NULL; 1947*2d586421SSepherosa Ziehau 1948*2d586421SSepherosa Ziehau return error; 1949*2d586421SSepherosa Ziehau } 1950*2d586421SSepherosa Ziehau } 1951*2d586421SSepherosa Ziehau 1952*2d586421SSepherosa Ziehau /* Create tag for Rx buffers. */ 1953*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 1954*2d586421SSepherosa Ziehau 1, 0, /* alignment, boundary */ 1955*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 1956*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 1957*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 1958*2d586421SSepherosa Ziehau MCLBYTES, /* maxsize */ 1959*2d586421SSepherosa Ziehau 1, /* nsegments */ 1960*2d586421SSepherosa Ziehau MCLBYTES, /* maxsegsize */ 1961*2d586421SSepherosa Ziehau 0, /* flags */ 1962*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_tag); 1963*2d586421SSepherosa Ziehau if (error) { 1964*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1965*2d586421SSepherosa Ziehau "failed to create Rx DMA tag\n"); 1966*2d586421SSepherosa Ziehau return error; 1967*2d586421SSepherosa Ziehau } 1968*2d586421SSepherosa Ziehau 1969*2d586421SSepherosa Ziehau /* Create DMA maps for Rx buffers. */ 1970*2d586421SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_rx_tag, 0, 1971*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_sparemap); 1972*2d586421SSepherosa Ziehau if (error) { 1973*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1974*2d586421SSepherosa Ziehau "failed to create spare Rx dmamap\n"); 1975*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 1976*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 1977*2d586421SSepherosa Ziehau return error; 1978*2d586421SSepherosa Ziehau } 1979*2d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 1980*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 1981*2d586421SSepherosa Ziehau 1982*2d586421SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_rx_tag, 0, 1983*2d586421SSepherosa Ziehau &rxd->rx_dmamap); 1984*2d586421SSepherosa Ziehau if (error) { 1985*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 1986*2d586421SSepherosa Ziehau "failed to create %dth Rx dmamap\n", i); 1987*2d586421SSepherosa Ziehau 1988*2d586421SSepherosa Ziehau for (j = 0; j < i; ++j) { 1989*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[j]; 1990*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 1991*2d586421SSepherosa Ziehau rxd->rx_dmamap); 1992*2d586421SSepherosa Ziehau } 1993*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 1994*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 1995*2d586421SSepherosa Ziehau 1996*2d586421SSepherosa Ziehau return error; 1997*2d586421SSepherosa Ziehau } 1998*2d586421SSepherosa Ziehau } 1999*2d586421SSepherosa Ziehau 2000*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2001*2d586421SSepherosa Ziehau SLIST_INIT(&sc_if->msk_jfree_listhead); 2002*2d586421SSepherosa Ziehau SLIST_INIT(&sc_if->msk_jinuse_listhead); 2003*2d586421SSepherosa Ziehau 2004*2d586421SSepherosa Ziehau /* Create tag for jumbo Rx ring. */ 2005*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 2006*2d586421SSepherosa Ziehau MSK_RING_ALIGN, 0, /* alignment, boundary */ 2007*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 2008*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 2009*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 2010*2d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_SZ, /* maxsize */ 2011*2d586421SSepherosa Ziehau 1, /* nsegments */ 2012*2d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_SZ, /* maxsegsize */ 2013*2d586421SSepherosa Ziehau 0, /* flags */ 2014*2d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 2015*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_ring_tag); 2016*2d586421SSepherosa Ziehau if (error != 0) { 2017*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2018*2d586421SSepherosa Ziehau "failed to create jumbo Rx ring DMA tag\n"); 2019*2d586421SSepherosa Ziehau goto fail; 2020*2d586421SSepherosa Ziehau } 2021*2d586421SSepherosa Ziehau 2022*2d586421SSepherosa Ziehau /* Allocate DMA'able memory and load the DMA map for jumbo Rx ring. */ 2023*2d586421SSepherosa Ziehau error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 2024*2d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_jumbo_rx_ring, 2025*2d586421SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 2026*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_ring_map); 2027*2d586421SSepherosa Ziehau if (error != 0) { 2028*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2029*2d586421SSepherosa Ziehau "failed to allocate DMA'able memory for jumbo Rx ring\n"); 2030*2d586421SSepherosa Ziehau goto fail; 2031*2d586421SSepherosa Ziehau } 2032*2d586421SSepherosa Ziehau 2033*2d586421SSepherosa Ziehau ctx.msk_busaddr = 0; 2034*2d586421SSepherosa Ziehau error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 2035*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 2036*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring, MSK_JUMBO_RX_RING_SZ, 2037*2d586421SSepherosa Ziehau msk_dmamap_cb, &ctx, 0); 2038*2d586421SSepherosa Ziehau if (error != 0) { 2039*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2040*2d586421SSepherosa Ziehau "failed to load DMA'able memory for jumbo Rx ring\n"); 2041*2d586421SSepherosa Ziehau goto fail; 2042*2d586421SSepherosa Ziehau } 2043*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring_paddr = ctx.msk_busaddr; 2044*2d586421SSepherosa Ziehau 2045*2d586421SSepherosa Ziehau /* Create tag for jumbo buffer blocks. */ 2046*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 2047*2d586421SSepherosa Ziehau PAGE_SIZE, 0, /* alignment, boundary */ 2048*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 2049*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 2050*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 2051*2d586421SSepherosa Ziehau MSK_JMEM, /* maxsize */ 2052*2d586421SSepherosa Ziehau 1, /* nsegments */ 2053*2d586421SSepherosa Ziehau MSK_JMEM, /* maxsegsize */ 2054*2d586421SSepherosa Ziehau 0, /* flags */ 2055*2d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 2056*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_tag); 2057*2d586421SSepherosa Ziehau if (error != 0) { 2058*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2059*2d586421SSepherosa Ziehau "failed to create jumbo Rx buffer block DMA tag\n"); 2060*2d586421SSepherosa Ziehau goto fail; 2061*2d586421SSepherosa Ziehau } 2062*2d586421SSepherosa Ziehau 2063*2d586421SSepherosa Ziehau /* Create tag for jumbo Rx buffers. */ 2064*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 2065*2d586421SSepherosa Ziehau PAGE_SIZE, 0, /* alignment, boundary */ 2066*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 2067*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 2068*2d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 2069*2d586421SSepherosa Ziehau MCLBYTES * MSK_MAXRXSEGS, /* maxsize */ 2070*2d586421SSepherosa Ziehau MSK_MAXRXSEGS, /* nsegments */ 2071*2d586421SSepherosa Ziehau MSK_JLEN, /* maxsegsize */ 2072*2d586421SSepherosa Ziehau 0, /* flags */ 2073*2d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 2074*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_tag); 2075*2d586421SSepherosa Ziehau if (error != 0) { 2076*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2077*2d586421SSepherosa Ziehau "failed to create jumbo Rx DMA tag\n"); 2078*2d586421SSepherosa Ziehau goto fail; 2079*2d586421SSepherosa Ziehau } 2080*2d586421SSepherosa Ziehau 2081*2d586421SSepherosa Ziehau /* Create DMA maps for jumbo Rx buffers. */ 2082*2d586421SSepherosa Ziehau if ((error = bus_dmamap_create(sc_if->msk_cdata.msk_jumbo_rx_tag, 0, 2083*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_sparemap)) != 0) { 2084*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2085*2d586421SSepherosa Ziehau "failed to create spare jumbo Rx dmamap\n"); 2086*2d586421SSepherosa Ziehau goto fail; 2087*2d586421SSepherosa Ziehau } 2088*2d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 2089*2d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 2090*2d586421SSepherosa Ziehau jrxd->rx_m = NULL; 2091*2d586421SSepherosa Ziehau jrxd->rx_dmamap = NULL; 2092*2d586421SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_jumbo_rx_tag, 0, 2093*2d586421SSepherosa Ziehau &jrxd->rx_dmamap); 2094*2d586421SSepherosa Ziehau if (error != 0) { 2095*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2096*2d586421SSepherosa Ziehau "failed to create jumbo Rx dmamap\n"); 2097*2d586421SSepherosa Ziehau goto fail; 2098*2d586421SSepherosa Ziehau } 2099*2d586421SSepherosa Ziehau } 2100*2d586421SSepherosa Ziehau 2101*2d586421SSepherosa Ziehau /* Allocate DMA'able memory and load the DMA map for jumbo buf. */ 2102*2d586421SSepherosa Ziehau error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_tag, 2103*2d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_jumbo_buf, 2104*2d586421SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 2105*2d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_map); 2106*2d586421SSepherosa Ziehau if (error != 0) { 2107*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2108*2d586421SSepherosa Ziehau "failed to allocate DMA'able memory for jumbo buf\n"); 2109*2d586421SSepherosa Ziehau goto fail; 2110*2d586421SSepherosa Ziehau } 2111*2d586421SSepherosa Ziehau 2112*2d586421SSepherosa Ziehau ctx.msk_busaddr = 0; 2113*2d586421SSepherosa Ziehau error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_tag, 2114*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map, sc_if->msk_rdata.msk_jumbo_buf, 2115*2d586421SSepherosa Ziehau MSK_JMEM, msk_dmamap_cb, &ctx, 0); 2116*2d586421SSepherosa Ziehau if (error != 0) { 2117*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2118*2d586421SSepherosa Ziehau "failed to load DMA'able memory for jumbobuf\n"); 2119*2d586421SSepherosa Ziehau goto fail; 2120*2d586421SSepherosa Ziehau } 2121*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf_paddr = ctx.msk_busaddr; 2122*2d586421SSepherosa Ziehau 2123*2d586421SSepherosa Ziehau /* 2124*2d586421SSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 2125*2d586421SSepherosa Ziehau * in an array. 2126*2d586421SSepherosa Ziehau */ 2127*2d586421SSepherosa Ziehau ptr = sc_if->msk_rdata.msk_jumbo_buf; 2128*2d586421SSepherosa Ziehau for (i = 0; i < MSK_JSLOTS; i++) { 2129*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jslots[i] = ptr; 2130*2d586421SSepherosa Ziehau ptr += MSK_JLEN; 2131*2d586421SSepherosa Ziehau entry = malloc(sizeof(struct msk_jpool_entry), 2132*2d586421SSepherosa Ziehau M_DEVBUF, M_WAITOK); 2133*2d586421SSepherosa Ziehau if (entry == NULL) { 2134*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2135*2d586421SSepherosa Ziehau "no memory for jumbo buffers!\n"); 2136*2d586421SSepherosa Ziehau error = ENOMEM; 2137*2d586421SSepherosa Ziehau goto fail; 2138*2d586421SSepherosa Ziehau } 2139*2d586421SSepherosa Ziehau entry->slot = i; 2140*2d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, 2141*2d586421SSepherosa Ziehau jpool_entries); 2142*2d586421SSepherosa Ziehau } 2143*2d586421SSepherosa Ziehau #endif 2144*2d586421SSepherosa Ziehau return 0; 2145*2d586421SSepherosa Ziehau } 2146*2d586421SSepherosa Ziehau 2147*2d586421SSepherosa Ziehau static void 2148*2d586421SSepherosa Ziehau msk_txrx_dma_free(struct msk_if_softc *sc_if) 2149*2d586421SSepherosa Ziehau { 2150*2d586421SSepherosa Ziehau struct msk_txdesc *txd; 2151*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 2152*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2153*2d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 2154*2d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 2155*2d586421SSepherosa Ziehau #endif 2156*2d586421SSepherosa Ziehau int i; 2157*2d586421SSepherosa Ziehau 2158*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2159*2d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 2160*2d586421SSepherosa Ziehau while ((entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead))) { 2161*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2162*2d586421SSepherosa Ziehau "asked to free buffer that is in use!\n"); 2163*2d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); 2164*2d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, 2165*2d586421SSepherosa Ziehau jpool_entries); 2166*2d586421SSepherosa Ziehau } 2167*2d586421SSepherosa Ziehau 2168*2d586421SSepherosa Ziehau while (!SLIST_EMPTY(&sc_if->msk_jfree_listhead)) { 2169*2d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); 2170*2d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); 2171*2d586421SSepherosa Ziehau free(entry, M_DEVBUF); 2172*2d586421SSepherosa Ziehau } 2173*2d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 2174*2d586421SSepherosa Ziehau 2175*2d586421SSepherosa Ziehau /* Destroy jumbo buffer block. */ 2176*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_map) 2177*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_tag, 2178*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map); 2179*2d586421SSepherosa Ziehau 2180*2d586421SSepherosa Ziehau if (sc_if->msk_rdata.msk_jumbo_buf) { 2181*2d586421SSepherosa Ziehau bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_tag, 2182*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf, 2183*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map); 2184*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf = NULL; 2185*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map = NULL; 2186*2d586421SSepherosa Ziehau } 2187*2d586421SSepherosa Ziehau 2188*2d586421SSepherosa Ziehau /* Jumbo Rx ring. */ 2189*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_tag) { 2190*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_map) 2191*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 2192*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map); 2193*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_map && 2194*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring) 2195*2d586421SSepherosa Ziehau bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 2196*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring, 2197*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map); 2198*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring = NULL; 2199*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map = NULL; 2200*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_ring_tag); 2201*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_tag = NULL; 2202*2d586421SSepherosa Ziehau } 2203*2d586421SSepherosa Ziehau 2204*2d586421SSepherosa Ziehau /* Jumbo Rx buffers. */ 2205*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_tag) { 2206*2d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 2207*2d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 2208*2d586421SSepherosa Ziehau if (jrxd->rx_dmamap) { 2209*2d586421SSepherosa Ziehau bus_dmamap_destroy( 2210*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_tag, 2211*2d586421SSepherosa Ziehau jrxd->rx_dmamap); 2212*2d586421SSepherosa Ziehau jrxd->rx_dmamap = NULL; 2213*2d586421SSepherosa Ziehau } 2214*2d586421SSepherosa Ziehau } 2215*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_sparemap) { 2216*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_jumbo_rx_tag, 2217*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap); 2218*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap = 0; 2219*2d586421SSepherosa Ziehau } 2220*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_tag); 2221*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_tag = NULL; 2222*2d586421SSepherosa Ziehau } 2223*2d586421SSepherosa Ziehau #endif 2224*2d586421SSepherosa Ziehau 2225*2d586421SSepherosa Ziehau /* Tx ring. */ 2226*2d586421SSepherosa Ziehau msk_dmamem_destroy(sc_if->msk_cdata.msk_tx_ring_tag, 2227*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_tx_ring, 2228*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_ring_map); 2229*2d586421SSepherosa Ziehau 2230*2d586421SSepherosa Ziehau /* Rx ring. */ 2231*2d586421SSepherosa Ziehau msk_dmamem_destroy(sc_if->msk_cdata.msk_rx_ring_tag, 2232*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_rx_ring, 2233*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_ring_map); 2234*2d586421SSepherosa Ziehau 2235*2d586421SSepherosa Ziehau /* Tx buffers. */ 2236*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_tag) { 2237*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 2238*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 2239*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_tx_tag, 2240*2d586421SSepherosa Ziehau txd->tx_dmamap); 2241*2d586421SSepherosa Ziehau } 2242*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_tx_tag); 2243*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_tag = NULL; 2244*2d586421SSepherosa Ziehau } 2245*2d586421SSepherosa Ziehau 2246*2d586421SSepherosa Ziehau /* Rx buffers. */ 2247*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_rx_tag) { 2248*2d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 2249*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 2250*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 2251*2d586421SSepherosa Ziehau rxd->rx_dmamap); 2252*2d586421SSepherosa Ziehau } 2253*2d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 2254*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap); 2255*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 2256*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 2257*2d586421SSepherosa Ziehau } 2258*2d586421SSepherosa Ziehau 2259*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_parent_tag) { 2260*2d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_parent_tag); 2261*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_parent_tag = NULL; 2262*2d586421SSepherosa Ziehau } 2263*2d586421SSepherosa Ziehau } 2264*2d586421SSepherosa Ziehau 2265*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2266*2d586421SSepherosa Ziehau /* 2267*2d586421SSepherosa Ziehau * Allocate a jumbo buffer. 2268*2d586421SSepherosa Ziehau */ 2269*2d586421SSepherosa Ziehau static void * 2270*2d586421SSepherosa Ziehau msk_jalloc(struct msk_if_softc *sc_if) 2271*2d586421SSepherosa Ziehau { 2272*2d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 2273*2d586421SSepherosa Ziehau 2274*2d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 2275*2d586421SSepherosa Ziehau 2276*2d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); 2277*2d586421SSepherosa Ziehau 2278*2d586421SSepherosa Ziehau if (entry == NULL) { 2279*2d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 2280*2d586421SSepherosa Ziehau return (NULL); 2281*2d586421SSepherosa Ziehau } 2282*2d586421SSepherosa Ziehau 2283*2d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); 2284*2d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jinuse_listhead, entry, jpool_entries); 2285*2d586421SSepherosa Ziehau 2286*2d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 2287*2d586421SSepherosa Ziehau 2288*2d586421SSepherosa Ziehau return (sc_if->msk_cdata.msk_jslots[entry->slot]); 2289*2d586421SSepherosa Ziehau } 2290*2d586421SSepherosa Ziehau 2291*2d586421SSepherosa Ziehau /* 2292*2d586421SSepherosa Ziehau * Release a jumbo buffer. 2293*2d586421SSepherosa Ziehau */ 2294*2d586421SSepherosa Ziehau static void 2295*2d586421SSepherosa Ziehau msk_jfree(void *buf, void *args) 2296*2d586421SSepherosa Ziehau { 2297*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 2298*2d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 2299*2d586421SSepherosa Ziehau int i; 2300*2d586421SSepherosa Ziehau 2301*2d586421SSepherosa Ziehau /* Extract the softc struct pointer. */ 2302*2d586421SSepherosa Ziehau sc_if = (struct msk_if_softc *)args; 2303*2d586421SSepherosa Ziehau KASSERT(sc_if != NULL, ("%s: can't find softc pointer!", __func__)); 2304*2d586421SSepherosa Ziehau 2305*2d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 2306*2d586421SSepherosa Ziehau /* Calculate the slot this buffer belongs to. */ 2307*2d586421SSepherosa Ziehau i = ((vm_offset_t)buf 2308*2d586421SSepherosa Ziehau - (vm_offset_t)sc_if->msk_rdata.msk_jumbo_buf) / MSK_JLEN; 2309*2d586421SSepherosa Ziehau KASSERT(i >= 0 && i < MSK_JSLOTS, 2310*2d586421SSepherosa Ziehau ("%s: asked to free buffer that we don't manage!", __func__)); 2311*2d586421SSepherosa Ziehau 2312*2d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead); 2313*2d586421SSepherosa Ziehau KASSERT(entry != NULL, ("%s: buffer not in use!", __func__)); 2314*2d586421SSepherosa Ziehau entry->slot = i; 2315*2d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); 2316*2d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, jpool_entries); 2317*2d586421SSepherosa Ziehau if (SLIST_EMPTY(&sc_if->msk_jinuse_listhead)) 2318*2d586421SSepherosa Ziehau wakeup(sc_if); 2319*2d586421SSepherosa Ziehau 2320*2d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 2321*2d586421SSepherosa Ziehau } 2322*2d586421SSepherosa Ziehau #endif 2323*2d586421SSepherosa Ziehau 2324*2d586421SSepherosa Ziehau /* 2325*2d586421SSepherosa Ziehau * It's copy of ath_defrag(ath(4)). 2326*2d586421SSepherosa Ziehau * 2327*2d586421SSepherosa Ziehau * Defragment an mbuf chain, returning at most maxfrags separate 2328*2d586421SSepherosa Ziehau * mbufs+clusters. If this is not possible NULL is returned and 2329*2d586421SSepherosa Ziehau * the original mbuf chain is left in it's present (potentially 2330*2d586421SSepherosa Ziehau * modified) state. We use two techniques: collapsing consecutive 2331*2d586421SSepherosa Ziehau * mbufs and replacing consecutive mbufs by a cluster. 2332*2d586421SSepherosa Ziehau */ 2333*2d586421SSepherosa Ziehau static struct mbuf * 2334*2d586421SSepherosa Ziehau msk_defrag(struct mbuf *m0, int how, int maxfrags) 2335*2d586421SSepherosa Ziehau { 2336*2d586421SSepherosa Ziehau struct mbuf *m, *n, *n2, **prev; 2337*2d586421SSepherosa Ziehau u_int curfrags; 2338*2d586421SSepherosa Ziehau 2339*2d586421SSepherosa Ziehau /* 2340*2d586421SSepherosa Ziehau * Calculate the current number of frags. 2341*2d586421SSepherosa Ziehau */ 2342*2d586421SSepherosa Ziehau curfrags = 0; 2343*2d586421SSepherosa Ziehau for (m = m0; m != NULL; m = m->m_next) 2344*2d586421SSepherosa Ziehau curfrags++; 2345*2d586421SSepherosa Ziehau /* 2346*2d586421SSepherosa Ziehau * First, try to collapse mbufs. Note that we always collapse 2347*2d586421SSepherosa Ziehau * towards the front so we don't need to deal with moving the 2348*2d586421SSepherosa Ziehau * pkthdr. This may be suboptimal if the first mbuf has much 2349*2d586421SSepherosa Ziehau * less data than the following. 2350*2d586421SSepherosa Ziehau */ 2351*2d586421SSepherosa Ziehau m = m0; 2352*2d586421SSepherosa Ziehau again: 2353*2d586421SSepherosa Ziehau for (;;) { 2354*2d586421SSepherosa Ziehau n = m->m_next; 2355*2d586421SSepherosa Ziehau if (n == NULL) 2356*2d586421SSepherosa Ziehau break; 2357*2d586421SSepherosa Ziehau if (n->m_len < M_TRAILINGSPACE(m)) { 2358*2d586421SSepherosa Ziehau bcopy(mtod(n, void *), mtod(m, char *) + m->m_len, 2359*2d586421SSepherosa Ziehau n->m_len); 2360*2d586421SSepherosa Ziehau m->m_len += n->m_len; 2361*2d586421SSepherosa Ziehau m->m_next = n->m_next; 2362*2d586421SSepherosa Ziehau m_free(n); 2363*2d586421SSepherosa Ziehau if (--curfrags <= maxfrags) 2364*2d586421SSepherosa Ziehau return (m0); 2365*2d586421SSepherosa Ziehau } else 2366*2d586421SSepherosa Ziehau m = n; 2367*2d586421SSepherosa Ziehau } 2368*2d586421SSepherosa Ziehau KASSERT(maxfrags > 1, 2369*2d586421SSepherosa Ziehau ("maxfrags %u, but normal collapse failed", maxfrags)); 2370*2d586421SSepherosa Ziehau /* 2371*2d586421SSepherosa Ziehau * Collapse consecutive mbufs to a cluster. 2372*2d586421SSepherosa Ziehau */ 2373*2d586421SSepherosa Ziehau prev = &m0->m_next; /* NB: not the first mbuf */ 2374*2d586421SSepherosa Ziehau while ((n = *prev) != NULL) { 2375*2d586421SSepherosa Ziehau if ((n2 = n->m_next) != NULL && 2376*2d586421SSepherosa Ziehau n->m_len + n2->m_len < MCLBYTES) { 2377*2d586421SSepherosa Ziehau m = m_getcl(how, MT_DATA, 0); 2378*2d586421SSepherosa Ziehau if (m == NULL) 2379*2d586421SSepherosa Ziehau goto bad; 2380*2d586421SSepherosa Ziehau bcopy(mtod(n, void *), mtod(m, void *), n->m_len); 2381*2d586421SSepherosa Ziehau bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len, 2382*2d586421SSepherosa Ziehau n2->m_len); 2383*2d586421SSepherosa Ziehau m->m_len = n->m_len + n2->m_len; 2384*2d586421SSepherosa Ziehau m->m_next = n2->m_next; 2385*2d586421SSepherosa Ziehau *prev = m; 2386*2d586421SSepherosa Ziehau m_free(n); 2387*2d586421SSepherosa Ziehau m_free(n2); 2388*2d586421SSepherosa Ziehau if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */ 2389*2d586421SSepherosa Ziehau return m0; 2390*2d586421SSepherosa Ziehau /* 2391*2d586421SSepherosa Ziehau * Still not there, try the normal collapse 2392*2d586421SSepherosa Ziehau * again before we allocate another cluster. 2393*2d586421SSepherosa Ziehau */ 2394*2d586421SSepherosa Ziehau goto again; 2395*2d586421SSepherosa Ziehau } 2396*2d586421SSepherosa Ziehau prev = &n->m_next; 2397*2d586421SSepherosa Ziehau } 2398*2d586421SSepherosa Ziehau /* 2399*2d586421SSepherosa Ziehau * No place where we can collapse to a cluster; punt. 2400*2d586421SSepherosa Ziehau * This can occur if, for example, you request 2 frags 2401*2d586421SSepherosa Ziehau * but the packet requires that both be clusters (we 2402*2d586421SSepherosa Ziehau * never reallocate the first mbuf to avoid moving the 2403*2d586421SSepherosa Ziehau * packet header). 2404*2d586421SSepherosa Ziehau */ 2405*2d586421SSepherosa Ziehau bad: 2406*2d586421SSepherosa Ziehau return (NULL); 2407*2d586421SSepherosa Ziehau } 2408*2d586421SSepherosa Ziehau 2409*2d586421SSepherosa Ziehau static int 2410*2d586421SSepherosa Ziehau msk_encap(struct msk_if_softc *sc_if, struct mbuf **m_head) 2411*2d586421SSepherosa Ziehau { 2412*2d586421SSepherosa Ziehau struct msk_txdesc *txd, *txd_last; 2413*2d586421SSepherosa Ziehau struct msk_tx_desc *tx_le; 2414*2d586421SSepherosa Ziehau struct mbuf *m; 2415*2d586421SSepherosa Ziehau bus_dmamap_t map; 2416*2d586421SSepherosa Ziehau struct msk_dmamap_arg ctx; 2417*2d586421SSepherosa Ziehau bus_dma_segment_t txsegs[MSK_MAXTXSEGS]; 2418*2d586421SSepherosa Ziehau uint32_t control, prod, si; 2419*2d586421SSepherosa Ziehau uint16_t offset, tcp_offset; 2420*2d586421SSepherosa Ziehau int error, i; 2421*2d586421SSepherosa Ziehau 2422*2d586421SSepherosa Ziehau tcp_offset = offset = 0; 2423*2d586421SSepherosa Ziehau m = *m_head; 2424*2d586421SSepherosa Ziehau if (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) { 2425*2d586421SSepherosa Ziehau /* 2426*2d586421SSepherosa Ziehau * Since mbuf has no protocol specific structure information 2427*2d586421SSepherosa Ziehau * in it we have to inspect protocol information here to 2428*2d586421SSepherosa Ziehau * setup TSO and checksum offload. I don't know why Marvell 2429*2d586421SSepherosa Ziehau * made a such decision in chip design because other GigE 2430*2d586421SSepherosa Ziehau * hardwares normally takes care of all these chores in 2431*2d586421SSepherosa Ziehau * hardware. However, TSO performance of Yukon II is very 2432*2d586421SSepherosa Ziehau * good such that it's worth to implement it. 2433*2d586421SSepherosa Ziehau */ 2434*2d586421SSepherosa Ziehau struct ether_header *eh; 2435*2d586421SSepherosa Ziehau struct ip *ip; 2436*2d586421SSepherosa Ziehau 2437*2d586421SSepherosa Ziehau /* TODO check for M_WRITABLE(m) */ 2438*2d586421SSepherosa Ziehau 2439*2d586421SSepherosa Ziehau offset = sizeof(struct ether_header); 2440*2d586421SSepherosa Ziehau m = m_pullup(m, offset); 2441*2d586421SSepherosa Ziehau if (m == NULL) { 2442*2d586421SSepherosa Ziehau *m_head = NULL; 2443*2d586421SSepherosa Ziehau return (ENOBUFS); 2444*2d586421SSepherosa Ziehau } 2445*2d586421SSepherosa Ziehau eh = mtod(m, struct ether_header *); 2446*2d586421SSepherosa Ziehau /* Check if hardware VLAN insertion is off. */ 2447*2d586421SSepherosa Ziehau if (eh->ether_type == htons(ETHERTYPE_VLAN)) { 2448*2d586421SSepherosa Ziehau offset = sizeof(struct ether_vlan_header); 2449*2d586421SSepherosa Ziehau m = m_pullup(m, offset); 2450*2d586421SSepherosa Ziehau if (m == NULL) { 2451*2d586421SSepherosa Ziehau *m_head = NULL; 2452*2d586421SSepherosa Ziehau return (ENOBUFS); 2453*2d586421SSepherosa Ziehau } 2454*2d586421SSepherosa Ziehau } 2455*2d586421SSepherosa Ziehau m = m_pullup(m, offset + sizeof(struct ip)); 2456*2d586421SSepherosa Ziehau if (m == NULL) { 2457*2d586421SSepherosa Ziehau *m_head = NULL; 2458*2d586421SSepherosa Ziehau return (ENOBUFS); 2459*2d586421SSepherosa Ziehau } 2460*2d586421SSepherosa Ziehau ip = (struct ip *)(mtod(m, char *) + offset); 2461*2d586421SSepherosa Ziehau offset += (ip->ip_hl << 2); 2462*2d586421SSepherosa Ziehau tcp_offset = offset; 2463*2d586421SSepherosa Ziehau /* 2464*2d586421SSepherosa Ziehau * It seems that Yukon II has Tx checksum offload bug for 2465*2d586421SSepherosa Ziehau * small TCP packets that's less than 60 bytes in size 2466*2d586421SSepherosa Ziehau * (e.g. TCP window probe packet, pure ACK packet). 2467*2d586421SSepherosa Ziehau * Common work around like padding with zeros to make the 2468*2d586421SSepherosa Ziehau * frame minimum ethernet frame size didn't work at all. 2469*2d586421SSepherosa Ziehau * Instead of disabling checksum offload completely we 2470*2d586421SSepherosa Ziehau * resort to S/W checksum routine when we encounter short 2471*2d586421SSepherosa Ziehau * TCP frames. 2472*2d586421SSepherosa Ziehau * Short UDP packets appear to be handled correctly by 2473*2d586421SSepherosa Ziehau * Yukon II. 2474*2d586421SSepherosa Ziehau */ 2475*2d586421SSepherosa Ziehau if (m->m_pkthdr.len < MSK_MIN_FRAMELEN && 2476*2d586421SSepherosa Ziehau (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { 2477*2d586421SSepherosa Ziehau uint16_t csum; 2478*2d586421SSepherosa Ziehau 2479*2d586421SSepherosa Ziehau csum = in_cksum_skip(m, ntohs(ip->ip_len) + offset - 2480*2d586421SSepherosa Ziehau (ip->ip_hl << 2), offset); 2481*2d586421SSepherosa Ziehau *(uint16_t *)(m->m_data + offset + 2482*2d586421SSepherosa Ziehau m->m_pkthdr.csum_data) = csum; 2483*2d586421SSepherosa Ziehau m->m_pkthdr.csum_flags &= ~CSUM_TCP; 2484*2d586421SSepherosa Ziehau } 2485*2d586421SSepherosa Ziehau *m_head = m; 2486*2d586421SSepherosa Ziehau } 2487*2d586421SSepherosa Ziehau 2488*2d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_tx_prod; 2489*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[prod]; 2490*2d586421SSepherosa Ziehau txd_last = txd; 2491*2d586421SSepherosa Ziehau map = txd->tx_dmamap; 2492*2d586421SSepherosa Ziehau bzero(&ctx, sizeof(ctx)); 2493*2d586421SSepherosa Ziehau ctx.nseg = MSK_MAXTXSEGS; 2494*2d586421SSepherosa Ziehau ctx.segs = txsegs; 2495*2d586421SSepherosa Ziehau error = bus_dmamap_load_mbuf(sc_if->msk_cdata.msk_tx_tag, map, 2496*2d586421SSepherosa Ziehau *m_head, msk_dmamap_mbuf_cb, &ctx, BUS_DMA_NOWAIT); 2497*2d586421SSepherosa Ziehau if (error == 0 && ctx.nseg == 0) { 2498*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, map); 2499*2d586421SSepherosa Ziehau error = EFBIG; 2500*2d586421SSepherosa Ziehau } 2501*2d586421SSepherosa Ziehau if (error == EFBIG) { 2502*2d586421SSepherosa Ziehau m = msk_defrag(*m_head, MB_DONTWAIT, MSK_MAXTXSEGS); 2503*2d586421SSepherosa Ziehau if (m == NULL) { 2504*2d586421SSepherosa Ziehau m_freem(*m_head); 2505*2d586421SSepherosa Ziehau *m_head = NULL; 2506*2d586421SSepherosa Ziehau return (ENOBUFS); 2507*2d586421SSepherosa Ziehau } 2508*2d586421SSepherosa Ziehau *m_head = m; 2509*2d586421SSepherosa Ziehau 2510*2d586421SSepherosa Ziehau bzero(&ctx, sizeof(ctx)); 2511*2d586421SSepherosa Ziehau ctx.nseg = MSK_MAXTXSEGS; 2512*2d586421SSepherosa Ziehau ctx.segs = txsegs; 2513*2d586421SSepherosa Ziehau error = bus_dmamap_load_mbuf(sc_if->msk_cdata.msk_tx_tag, 2514*2d586421SSepherosa Ziehau map, *m_head, msk_dmamap_mbuf_cb, &ctx, BUS_DMA_NOWAIT); 2515*2d586421SSepherosa Ziehau if (error == 0 && ctx.nseg == 0) { 2516*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, map); 2517*2d586421SSepherosa Ziehau error = EFBIG; 2518*2d586421SSepherosa Ziehau } 2519*2d586421SSepherosa Ziehau if (error != 0) { 2520*2d586421SSepherosa Ziehau m_freem(*m_head); 2521*2d586421SSepherosa Ziehau *m_head = NULL; 2522*2d586421SSepherosa Ziehau return (error); 2523*2d586421SSepherosa Ziehau } 2524*2d586421SSepherosa Ziehau } else if (error != 0) { 2525*2d586421SSepherosa Ziehau return (error); 2526*2d586421SSepherosa Ziehau } 2527*2d586421SSepherosa Ziehau 2528*2d586421SSepherosa Ziehau /* Check number of available descriptors. */ 2529*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt + ctx.nseg >= 2530*2d586421SSepherosa Ziehau (MSK_TX_RING_CNT - MSK_RESERVED_TX_DESC_CNT)) { 2531*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, map); 2532*2d586421SSepherosa Ziehau return (ENOBUFS); 2533*2d586421SSepherosa Ziehau } 2534*2d586421SSepherosa Ziehau 2535*2d586421SSepherosa Ziehau control = 0; 2536*2d586421SSepherosa Ziehau tx_le = NULL; 2537*2d586421SSepherosa Ziehau 2538*2d586421SSepherosa Ziehau #ifdef notyet 2539*2d586421SSepherosa Ziehau /* Check if we have a VLAN tag to insert. */ 2540*2d586421SSepherosa Ziehau if ((m->m_flags & M_VLANTAG) != 0) { 2541*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 2542*2d586421SSepherosa Ziehau tx_le->msk_addr = htole32(0); 2543*2d586421SSepherosa Ziehau tx_le->msk_control = htole32(OP_VLAN | HW_OWNER | 2544*2d586421SSepherosa Ziehau htons(m->m_pkthdr.ether_vtag)); 2545*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 2546*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 2547*2d586421SSepherosa Ziehau control |= INS_VLAN; 2548*2d586421SSepherosa Ziehau } 2549*2d586421SSepherosa Ziehau #endif 2550*2d586421SSepherosa Ziehau /* Check if we have to handle checksum offload. */ 2551*2d586421SSepherosa Ziehau if (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) { 2552*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 2553*2d586421SSepherosa Ziehau tx_le->msk_addr = htole32(((tcp_offset + m->m_pkthdr.csum_data) 2554*2d586421SSepherosa Ziehau & 0xffff) | ((uint32_t)tcp_offset << 16)); 2555*2d586421SSepherosa Ziehau tx_le->msk_control = htole32(1 << 16 | (OP_TCPLISW | HW_OWNER)); 2556*2d586421SSepherosa Ziehau control = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; 2557*2d586421SSepherosa Ziehau if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) 2558*2d586421SSepherosa Ziehau control |= UDPTCP; 2559*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 2560*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 2561*2d586421SSepherosa Ziehau } 2562*2d586421SSepherosa Ziehau 2563*2d586421SSepherosa Ziehau si = prod; 2564*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 2565*2d586421SSepherosa Ziehau tx_le->msk_addr = htole32(MSK_ADDR_LO(txsegs[0].ds_addr)); 2566*2d586421SSepherosa Ziehau tx_le->msk_control = htole32(txsegs[0].ds_len | control | 2567*2d586421SSepherosa Ziehau OP_PACKET); 2568*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 2569*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 2570*2d586421SSepherosa Ziehau 2571*2d586421SSepherosa Ziehau for (i = 1; i < ctx.nseg; i++) { 2572*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 2573*2d586421SSepherosa Ziehau tx_le->msk_addr = htole32(MSK_ADDR_LO(txsegs[i].ds_addr)); 2574*2d586421SSepherosa Ziehau tx_le->msk_control = htole32(txsegs[i].ds_len | control | 2575*2d586421SSepherosa Ziehau OP_BUFFER | HW_OWNER); 2576*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 2577*2d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 2578*2d586421SSepherosa Ziehau } 2579*2d586421SSepherosa Ziehau /* Update producer index. */ 2580*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod = prod; 2581*2d586421SSepherosa Ziehau 2582*2d586421SSepherosa Ziehau /* Set EOP on the last desciptor. */ 2583*2d586421SSepherosa Ziehau prod = (prod + MSK_TX_RING_CNT - 1) % MSK_TX_RING_CNT; 2584*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 2585*2d586421SSepherosa Ziehau tx_le->msk_control |= htole32(EOP); 2586*2d586421SSepherosa Ziehau 2587*2d586421SSepherosa Ziehau /* Turn the first descriptor ownership to hardware. */ 2588*2d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[si]; 2589*2d586421SSepherosa Ziehau tx_le->msk_control |= htole32(HW_OWNER); 2590*2d586421SSepherosa Ziehau 2591*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[prod]; 2592*2d586421SSepherosa Ziehau map = txd_last->tx_dmamap; 2593*2d586421SSepherosa Ziehau txd_last->tx_dmamap = txd->tx_dmamap; 2594*2d586421SSepherosa Ziehau txd->tx_dmamap = map; 2595*2d586421SSepherosa Ziehau txd->tx_m = m; 2596*2d586421SSepherosa Ziehau 2597*2d586421SSepherosa Ziehau /* Sync descriptors. */ 2598*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_tag, map, BUS_DMASYNC_PREWRITE); 2599*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_ring_tag, 2600*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_ring_map, BUS_DMASYNC_PREWRITE); 2601*2d586421SSepherosa Ziehau 2602*2d586421SSepherosa Ziehau return (0); 2603*2d586421SSepherosa Ziehau } 2604*2d586421SSepherosa Ziehau 2605*2d586421SSepherosa Ziehau static void 2606*2d586421SSepherosa Ziehau msk_start(struct ifnet *ifp) 2607*2d586421SSepherosa Ziehau { 2608*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 2609*2d586421SSepherosa Ziehau struct mbuf *m_head; 2610*2d586421SSepherosa Ziehau int enq; 2611*2d586421SSepherosa Ziehau 2612*2d586421SSepherosa Ziehau sc_if = ifp->if_softc; 2613*2d586421SSepherosa Ziehau 2614*2d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 2615*2d586421SSepherosa Ziehau 2616*2d586421SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != 2617*2d586421SSepherosa Ziehau IFF_RUNNING || sc_if->msk_link == 0) 2618*2d586421SSepherosa Ziehau return; 2619*2d586421SSepherosa Ziehau 2620*2d586421SSepherosa Ziehau for (enq = 0; !ifq_is_empty(&ifp->if_snd) && 2621*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt < 2622*2d586421SSepherosa Ziehau (MSK_TX_RING_CNT - MSK_RESERVED_TX_DESC_CNT); ) { 2623*2d586421SSepherosa Ziehau m_head = ifq_dequeue(&ifp->if_snd, NULL); 2624*2d586421SSepherosa Ziehau if (m_head == NULL) 2625*2d586421SSepherosa Ziehau break; 2626*2d586421SSepherosa Ziehau 2627*2d586421SSepherosa Ziehau /* 2628*2d586421SSepherosa Ziehau * Pack the data into the transmit ring. If we 2629*2d586421SSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 2630*2d586421SSepherosa Ziehau * for the NIC to drain the ring. 2631*2d586421SSepherosa Ziehau */ 2632*2d586421SSepherosa Ziehau if (msk_encap(sc_if, &m_head) != 0) { 2633*2d586421SSepherosa Ziehau if (m_head == NULL) 2634*2d586421SSepherosa Ziehau break; 2635*2d586421SSepherosa Ziehau m_freem(m_head); 2636*2d586421SSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 2637*2d586421SSepherosa Ziehau break; 2638*2d586421SSepherosa Ziehau } 2639*2d586421SSepherosa Ziehau 2640*2d586421SSepherosa Ziehau enq++; 2641*2d586421SSepherosa Ziehau /* 2642*2d586421SSepherosa Ziehau * If there's a BPF listener, bounce a copy of this frame 2643*2d586421SSepherosa Ziehau * to him. 2644*2d586421SSepherosa Ziehau */ 2645*2d586421SSepherosa Ziehau BPF_MTAP(ifp, m_head); 2646*2d586421SSepherosa Ziehau } 2647*2d586421SSepherosa Ziehau 2648*2d586421SSepherosa Ziehau if (enq > 0) { 2649*2d586421SSepherosa Ziehau /* Transmit */ 2650*2d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 2651*2d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_txq, PREF_UNIT_PUT_IDX_REG), 2652*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod); 2653*2d586421SSepherosa Ziehau 2654*2d586421SSepherosa Ziehau /* Set a timeout in case the chip goes out to lunch. */ 2655*2d586421SSepherosa Ziehau ifp->if_timer = MSK_TX_TIMEOUT; 2656*2d586421SSepherosa Ziehau } 2657*2d586421SSepherosa Ziehau } 2658*2d586421SSepherosa Ziehau 2659*2d586421SSepherosa Ziehau static void 2660*2d586421SSepherosa Ziehau msk_watchdog(struct ifnet *ifp) 2661*2d586421SSepherosa Ziehau { 2662*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 2663*2d586421SSepherosa Ziehau uint32_t ridx; 2664*2d586421SSepherosa Ziehau int idx; 2665*2d586421SSepherosa Ziehau 2666*2d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 2667*2d586421SSepherosa Ziehau 2668*2d586421SSepherosa Ziehau if (sc_if->msk_link == 0) { 2669*2d586421SSepherosa Ziehau if (bootverbose) 2670*2d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "watchdog timeout " 2671*2d586421SSepherosa Ziehau "(missed link)\n"); 2672*2d586421SSepherosa Ziehau ifp->if_oerrors++; 2673*2d586421SSepherosa Ziehau msk_init(sc_if); 2674*2d586421SSepherosa Ziehau return; 2675*2d586421SSepherosa Ziehau } 2676*2d586421SSepherosa Ziehau 2677*2d586421SSepherosa Ziehau /* 2678*2d586421SSepherosa Ziehau * Reclaim first as there is a possibility of losing Tx completion 2679*2d586421SSepherosa Ziehau * interrupts. 2680*2d586421SSepherosa Ziehau */ 2681*2d586421SSepherosa Ziehau ridx = sc_if->msk_port == MSK_PORT_A ? STAT_TXA1_RIDX : STAT_TXA2_RIDX; 2682*2d586421SSepherosa Ziehau idx = CSR_READ_2(sc_if->msk_softc, ridx); 2683*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cons != idx) { 2684*2d586421SSepherosa Ziehau msk_txeof(sc_if, idx); 2685*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt == 0) { 2686*2d586421SSepherosa Ziehau if_printf(ifp, "watchdog timeout (missed Tx interrupts) " 2687*2d586421SSepherosa Ziehau "-- recovering\n"); 2688*2d586421SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 2689*2d586421SSepherosa Ziehau ifp->if_start(ifp); 2690*2d586421SSepherosa Ziehau return; 2691*2d586421SSepherosa Ziehau } 2692*2d586421SSepherosa Ziehau } 2693*2d586421SSepherosa Ziehau 2694*2d586421SSepherosa Ziehau if_printf(ifp, "watchdog timeout\n"); 2695*2d586421SSepherosa Ziehau ifp->if_oerrors++; 2696*2d586421SSepherosa Ziehau msk_init(sc_if); 2697*2d586421SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 2698*2d586421SSepherosa Ziehau ifp->if_start(ifp); 2699*2d586421SSepherosa Ziehau } 2700*2d586421SSepherosa Ziehau 2701*2d586421SSepherosa Ziehau static int 2702*2d586421SSepherosa Ziehau mskc_shutdown(device_t dev) 2703*2d586421SSepherosa Ziehau { 2704*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 2705*2d586421SSepherosa Ziehau int i; 2706*2d586421SSepherosa Ziehau 2707*2d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 2708*2d586421SSepherosa Ziehau 2709*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 2710*2d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL) 2711*2d586421SSepherosa Ziehau msk_stop(sc->msk_if[i]); 2712*2d586421SSepherosa Ziehau } 2713*2d586421SSepherosa Ziehau 2714*2d586421SSepherosa Ziehau /* Disable all interrupts. */ 2715*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 2716*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 2717*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 2718*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 2719*2d586421SSepherosa Ziehau 2720*2d586421SSepherosa Ziehau /* Put hardware reset. */ 2721*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 2722*2d586421SSepherosa Ziehau 2723*2d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 2724*2d586421SSepherosa Ziehau return (0); 2725*2d586421SSepherosa Ziehau } 2726*2d586421SSepherosa Ziehau 2727*2d586421SSepherosa Ziehau static int 2728*2d586421SSepherosa Ziehau mskc_suspend(device_t dev) 2729*2d586421SSepherosa Ziehau { 2730*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 2731*2d586421SSepherosa Ziehau int i; 2732*2d586421SSepherosa Ziehau 2733*2d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 2734*2d586421SSepherosa Ziehau 2735*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 2736*2d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && 2737*2d586421SSepherosa Ziehau ((sc->msk_if[i]->msk_ifp->if_flags & IFF_RUNNING) != 0)) 2738*2d586421SSepherosa Ziehau msk_stop(sc->msk_if[i]); 2739*2d586421SSepherosa Ziehau } 2740*2d586421SSepherosa Ziehau 2741*2d586421SSepherosa Ziehau /* Disable all interrupts. */ 2742*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 2743*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 2744*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 2745*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 2746*2d586421SSepherosa Ziehau 2747*2d586421SSepherosa Ziehau mskc_phy_power(sc, MSK_PHY_POWERDOWN); 2748*2d586421SSepherosa Ziehau 2749*2d586421SSepherosa Ziehau /* Put hardware reset. */ 2750*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 2751*2d586421SSepherosa Ziehau sc->msk_suspended = 1; 2752*2d586421SSepherosa Ziehau 2753*2d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 2754*2d586421SSepherosa Ziehau 2755*2d586421SSepherosa Ziehau return (0); 2756*2d586421SSepherosa Ziehau } 2757*2d586421SSepherosa Ziehau 2758*2d586421SSepherosa Ziehau static int 2759*2d586421SSepherosa Ziehau mskc_resume(device_t dev) 2760*2d586421SSepherosa Ziehau { 2761*2d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 2762*2d586421SSepherosa Ziehau int i; 2763*2d586421SSepherosa Ziehau 2764*2d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 2765*2d586421SSepherosa Ziehau 2766*2d586421SSepherosa Ziehau mskc_reset(sc); 2767*2d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 2768*2d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && 2769*2d586421SSepherosa Ziehau ((sc->msk_if[i]->msk_ifp->if_flags & IFF_UP) != 0)) 2770*2d586421SSepherosa Ziehau msk_init(sc->msk_if[i]); 2771*2d586421SSepherosa Ziehau } 2772*2d586421SSepherosa Ziehau sc->msk_suspended = 0; 2773*2d586421SSepherosa Ziehau 2774*2d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 2775*2d586421SSepherosa Ziehau 2776*2d586421SSepherosa Ziehau return (0); 2777*2d586421SSepherosa Ziehau } 2778*2d586421SSepherosa Ziehau 2779*2d586421SSepherosa Ziehau static void 2780*2d586421SSepherosa Ziehau msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) 2781*2d586421SSepherosa Ziehau { 2782*2d586421SSepherosa Ziehau struct mbuf *m; 2783*2d586421SSepherosa Ziehau struct ifnet *ifp; 2784*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 2785*2d586421SSepherosa Ziehau int cons, rxlen; 2786*2d586421SSepherosa Ziehau 2787*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 2788*2d586421SSepherosa Ziehau 2789*2d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_rx_cons; 2790*2d586421SSepherosa Ziehau do { 2791*2d586421SSepherosa Ziehau rxlen = status >> 16; 2792*2d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 2793*2d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 2794*2d586421SSepherosa Ziehau rxlen -= EVL_ENCAPLEN; 2795*2d586421SSepherosa Ziehau if (len > sc_if->msk_framesize || 2796*2d586421SSepherosa Ziehau ((status & GMR_FS_ANY_ERR) != 0) || 2797*2d586421SSepherosa Ziehau ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) { 2798*2d586421SSepherosa Ziehau /* Don't count flow-control packet as errors. */ 2799*2d586421SSepherosa Ziehau if ((status & GMR_FS_GOOD_FC) == 0) 2800*2d586421SSepherosa Ziehau ifp->if_ierrors++; 2801*2d586421SSepherosa Ziehau msk_discard_rxbuf(sc_if, cons); 2802*2d586421SSepherosa Ziehau break; 2803*2d586421SSepherosa Ziehau } 2804*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[cons]; 2805*2d586421SSepherosa Ziehau m = rxd->rx_m; 2806*2d586421SSepherosa Ziehau if (msk_newbuf(sc_if, cons) != 0) { 2807*2d586421SSepherosa Ziehau ifp->if_iqdrops++; 2808*2d586421SSepherosa Ziehau /* Reuse old buffer. */ 2809*2d586421SSepherosa Ziehau msk_discard_rxbuf(sc_if, cons); 2810*2d586421SSepherosa Ziehau break; 2811*2d586421SSepherosa Ziehau } 2812*2d586421SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 2813*2d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 2814*2d586421SSepherosa Ziehau ifp->if_ipackets++; 2815*2d586421SSepherosa Ziehau #ifdef notyet 2816*2d586421SSepherosa Ziehau /* Check for VLAN tagged packets. */ 2817*2d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 2818*2d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 2819*2d586421SSepherosa Ziehau m->m_pkthdr.ether_vtag = sc_if->msk_vtag; 2820*2d586421SSepherosa Ziehau m->m_flags |= M_VLANTAG; 2821*2d586421SSepherosa Ziehau } 2822*2d586421SSepherosa Ziehau #endif 2823*2d586421SSepherosa Ziehau ifp->if_input(ifp, m); 2824*2d586421SSepherosa Ziehau } while (0); 2825*2d586421SSepherosa Ziehau 2826*2d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_cons, MSK_RX_RING_CNT); 2827*2d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_prod, MSK_RX_RING_CNT); 2828*2d586421SSepherosa Ziehau } 2829*2d586421SSepherosa Ziehau 2830*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2831*2d586421SSepherosa Ziehau static void 2832*2d586421SSepherosa Ziehau msk_jumbo_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) 2833*2d586421SSepherosa Ziehau { 2834*2d586421SSepherosa Ziehau struct mbuf *m; 2835*2d586421SSepherosa Ziehau struct ifnet *ifp; 2836*2d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 2837*2d586421SSepherosa Ziehau int cons, rxlen; 2838*2d586421SSepherosa Ziehau 2839*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 2840*2d586421SSepherosa Ziehau 2841*2d586421SSepherosa Ziehau MSK_IF_LOCK_ASSERT(sc_if); 2842*2d586421SSepherosa Ziehau 2843*2d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_rx_cons; 2844*2d586421SSepherosa Ziehau do { 2845*2d586421SSepherosa Ziehau rxlen = status >> 16; 2846*2d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 2847*2d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 2848*2d586421SSepherosa Ziehau rxlen -= ETHER_VLAN_ENCAP_LEN; 2849*2d586421SSepherosa Ziehau if (len > sc_if->msk_framesize || 2850*2d586421SSepherosa Ziehau ((status & GMR_FS_ANY_ERR) != 0) || 2851*2d586421SSepherosa Ziehau ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) { 2852*2d586421SSepherosa Ziehau /* Don't count flow-control packet as errors. */ 2853*2d586421SSepherosa Ziehau if ((status & GMR_FS_GOOD_FC) == 0) 2854*2d586421SSepherosa Ziehau ifp->if_ierrors++; 2855*2d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(sc_if, cons); 2856*2d586421SSepherosa Ziehau break; 2857*2d586421SSepherosa Ziehau } 2858*2d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[cons]; 2859*2d586421SSepherosa Ziehau m = jrxd->rx_m; 2860*2d586421SSepherosa Ziehau if (msk_jumbo_newbuf(sc_if, cons) != 0) { 2861*2d586421SSepherosa Ziehau ifp->if_iqdrops++; 2862*2d586421SSepherosa Ziehau /* Reuse old buffer. */ 2863*2d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(sc_if, cons); 2864*2d586421SSepherosa Ziehau break; 2865*2d586421SSepherosa Ziehau } 2866*2d586421SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 2867*2d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 2868*2d586421SSepherosa Ziehau ifp->if_ipackets++; 2869*2d586421SSepherosa Ziehau /* Check for VLAN tagged packets. */ 2870*2d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 2871*2d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 2872*2d586421SSepherosa Ziehau m->m_pkthdr.ether_vtag = sc_if->msk_vtag; 2873*2d586421SSepherosa Ziehau m->m_flags |= M_VLANTAG; 2874*2d586421SSepherosa Ziehau } 2875*2d586421SSepherosa Ziehau MSK_IF_UNLOCK(sc_if); 2876*2d586421SSepherosa Ziehau (*ifp->if_input)(ifp, m); 2877*2d586421SSepherosa Ziehau MSK_IF_LOCK(sc_if); 2878*2d586421SSepherosa Ziehau } while (0); 2879*2d586421SSepherosa Ziehau 2880*2d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_cons, MSK_JUMBO_RX_RING_CNT); 2881*2d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_prod, MSK_JUMBO_RX_RING_CNT); 2882*2d586421SSepherosa Ziehau } 2883*2d586421SSepherosa Ziehau #endif 2884*2d586421SSepherosa Ziehau 2885*2d586421SSepherosa Ziehau static void 2886*2d586421SSepherosa Ziehau msk_txeof(struct msk_if_softc *sc_if, int idx) 2887*2d586421SSepherosa Ziehau { 2888*2d586421SSepherosa Ziehau struct msk_txdesc *txd; 2889*2d586421SSepherosa Ziehau struct msk_tx_desc *cur_tx; 2890*2d586421SSepherosa Ziehau struct ifnet *ifp; 2891*2d586421SSepherosa Ziehau uint32_t control; 2892*2d586421SSepherosa Ziehau int cons, prog; 2893*2d586421SSepherosa Ziehau 2894*2d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 2895*2d586421SSepherosa Ziehau 2896*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_ring_tag, 2897*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_ring_map, BUS_DMASYNC_POSTREAD); 2898*2d586421SSepherosa Ziehau 2899*2d586421SSepherosa Ziehau /* 2900*2d586421SSepherosa Ziehau * Go through our tx ring and free mbufs for those 2901*2d586421SSepherosa Ziehau * frames that have been sent. 2902*2d586421SSepherosa Ziehau */ 2903*2d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_tx_cons; 2904*2d586421SSepherosa Ziehau prog = 0; 2905*2d586421SSepherosa Ziehau for (; cons != idx; MSK_INC(cons, MSK_TX_RING_CNT)) { 2906*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt <= 0) 2907*2d586421SSepherosa Ziehau break; 2908*2d586421SSepherosa Ziehau prog++; 2909*2d586421SSepherosa Ziehau cur_tx = &sc_if->msk_rdata.msk_tx_ring[cons]; 2910*2d586421SSepherosa Ziehau control = le32toh(cur_tx->msk_control); 2911*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt--; 2912*2d586421SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 2913*2d586421SSepherosa Ziehau if ((control & EOP) == 0) 2914*2d586421SSepherosa Ziehau continue; 2915*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[cons]; 2916*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_tag, txd->tx_dmamap, 2917*2d586421SSepherosa Ziehau BUS_DMASYNC_POSTWRITE); 2918*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, txd->tx_dmamap); 2919*2d586421SSepherosa Ziehau 2920*2d586421SSepherosa Ziehau ifp->if_opackets++; 2921*2d586421SSepherosa Ziehau KASSERT(txd->tx_m != NULL, ("%s: freeing NULL mbuf!", 2922*2d586421SSepherosa Ziehau __func__)); 2923*2d586421SSepherosa Ziehau m_freem(txd->tx_m); 2924*2d586421SSepherosa Ziehau txd->tx_m = NULL; 2925*2d586421SSepherosa Ziehau } 2926*2d586421SSepherosa Ziehau 2927*2d586421SSepherosa Ziehau if (prog > 0) { 2928*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cons = cons; 2929*2d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt == 0) 2930*2d586421SSepherosa Ziehau ifp->if_timer = 0; 2931*2d586421SSepherosa Ziehau /* No need to sync LEs as we didn't update LEs. */ 2932*2d586421SSepherosa Ziehau } 2933*2d586421SSepherosa Ziehau } 2934*2d586421SSepherosa Ziehau 2935*2d586421SSepherosa Ziehau static void 2936*2d586421SSepherosa Ziehau msk_tick(void *xsc_if) 2937*2d586421SSepherosa Ziehau { 2938*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = xsc_if; 2939*2d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 2940*2d586421SSepherosa Ziehau struct mii_data *mii; 2941*2d586421SSepherosa Ziehau 2942*2d586421SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2943*2d586421SSepherosa Ziehau 2944*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 2945*2d586421SSepherosa Ziehau 2946*2d586421SSepherosa Ziehau mii_tick(mii); 2947*2d586421SSepherosa Ziehau callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if); 2948*2d586421SSepherosa Ziehau 2949*2d586421SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2950*2d586421SSepherosa Ziehau } 2951*2d586421SSepherosa Ziehau 2952*2d586421SSepherosa Ziehau static void 2953*2d586421SSepherosa Ziehau msk_intr_phy(struct msk_if_softc *sc_if) 2954*2d586421SSepherosa Ziehau { 2955*2d586421SSepherosa Ziehau uint16_t status; 2956*2d586421SSepherosa Ziehau 2957*2d586421SSepherosa Ziehau msk_phy_readreg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_STAT); 2958*2d586421SSepherosa Ziehau status = msk_phy_readreg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_STAT); 2959*2d586421SSepherosa Ziehau /* Handle FIFO Underrun/Overflow? */ 2960*2d586421SSepherosa Ziehau if (status & PHY_M_IS_FIFO_ERROR) { 2961*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 2962*2d586421SSepherosa Ziehau "PHY FIFO underrun/overflow.\n"); 2963*2d586421SSepherosa Ziehau } 2964*2d586421SSepherosa Ziehau } 2965*2d586421SSepherosa Ziehau 2966*2d586421SSepherosa Ziehau static void 2967*2d586421SSepherosa Ziehau msk_intr_gmac(struct msk_if_softc *sc_if) 2968*2d586421SSepherosa Ziehau { 2969*2d586421SSepherosa Ziehau struct msk_softc *sc; 2970*2d586421SSepherosa Ziehau uint8_t status; 2971*2d586421SSepherosa Ziehau 2972*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 2973*2d586421SSepherosa Ziehau status = CSR_READ_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_SRC)); 2974*2d586421SSepherosa Ziehau 2975*2d586421SSepherosa Ziehau /* GMAC Rx FIFO overrun. */ 2976*2d586421SSepherosa Ziehau if ((status & GM_IS_RX_FF_OR) != 0) { 2977*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 2978*2d586421SSepherosa Ziehau GMF_CLI_RX_FO); 2979*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Rx FIFO overrun!\n"); 2980*2d586421SSepherosa Ziehau } 2981*2d586421SSepherosa Ziehau /* GMAC Tx FIFO underrun. */ 2982*2d586421SSepherosa Ziehau if ((status & GM_IS_TX_FF_UR) != 0) { 2983*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 2984*2d586421SSepherosa Ziehau GMF_CLI_TX_FU); 2985*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx FIFO underrun!\n"); 2986*2d586421SSepherosa Ziehau /* 2987*2d586421SSepherosa Ziehau * XXX 2988*2d586421SSepherosa Ziehau * In case of Tx underrun, we may need to flush/reset 2989*2d586421SSepherosa Ziehau * Tx MAC but that would also require resynchronization 2990*2d586421SSepherosa Ziehau * with status LEs. Reintializing status LEs would 2991*2d586421SSepherosa Ziehau * affect other port in dual MAC configuration so it 2992*2d586421SSepherosa Ziehau * should be avoided as possible as we can. 2993*2d586421SSepherosa Ziehau * Due to lack of documentation it's all vague guess but 2994*2d586421SSepherosa Ziehau * it needs more investigation. 2995*2d586421SSepherosa Ziehau */ 2996*2d586421SSepherosa Ziehau } 2997*2d586421SSepherosa Ziehau } 2998*2d586421SSepherosa Ziehau 2999*2d586421SSepherosa Ziehau static void 3000*2d586421SSepherosa Ziehau msk_handle_hwerr(struct msk_if_softc *sc_if, uint32_t status) 3001*2d586421SSepherosa Ziehau { 3002*2d586421SSepherosa Ziehau struct msk_softc *sc; 3003*2d586421SSepherosa Ziehau 3004*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 3005*2d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_RD1) != 0) { 3006*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 3007*2d586421SSepherosa Ziehau "RAM buffer read parity error\n"); 3008*2d586421SSepherosa Ziehau /* Clear IRQ. */ 3009*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(sc_if->msk_port, B3_RI_CTRL), 3010*2d586421SSepherosa Ziehau RI_CLR_RD_PERR); 3011*2d586421SSepherosa Ziehau } 3012*2d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_WR1) != 0) { 3013*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 3014*2d586421SSepherosa Ziehau "RAM buffer write parity error\n"); 3015*2d586421SSepherosa Ziehau /* Clear IRQ. */ 3016*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(sc_if->msk_port, B3_RI_CTRL), 3017*2d586421SSepherosa Ziehau RI_CLR_WR_PERR); 3018*2d586421SSepherosa Ziehau } 3019*2d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_MAC1) != 0) { 3020*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx MAC parity error\n"); 3021*2d586421SSepherosa Ziehau /* Clear IRQ. */ 3022*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 3023*2d586421SSepherosa Ziehau GMF_CLI_TX_PE); 3024*2d586421SSepherosa Ziehau } 3025*2d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_RX1) != 0) { 3026*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Rx parity error\n"); 3027*2d586421SSepherosa Ziehau /* Clear IRQ. */ 3028*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_CLR_IRQ_PAR); 3029*2d586421SSepherosa Ziehau } 3030*2d586421SSepherosa Ziehau if ((status & (Y2_IS_TCP_TXS1 | Y2_IS_TCP_TXA1)) != 0) { 3031*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "TCP segmentation error\n"); 3032*2d586421SSepherosa Ziehau /* Clear IRQ. */ 3033*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_CLR_IRQ_TCP); 3034*2d586421SSepherosa Ziehau } 3035*2d586421SSepherosa Ziehau } 3036*2d586421SSepherosa Ziehau 3037*2d586421SSepherosa Ziehau static void 3038*2d586421SSepherosa Ziehau mskc_intr_hwerr(struct msk_softc *sc) 3039*2d586421SSepherosa Ziehau { 3040*2d586421SSepherosa Ziehau uint32_t status; 3041*2d586421SSepherosa Ziehau uint32_t tlphead[4]; 3042*2d586421SSepherosa Ziehau 3043*2d586421SSepherosa Ziehau status = CSR_READ_4(sc, B0_HWE_ISRC); 3044*2d586421SSepherosa Ziehau /* Time Stamp timer overflow. */ 3045*2d586421SSepherosa Ziehau if ((status & Y2_IS_TIST_OV) != 0) 3046*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); 3047*2d586421SSepherosa Ziehau if ((status & Y2_IS_PCI_NEXP) != 0) { 3048*2d586421SSepherosa Ziehau /* 3049*2d586421SSepherosa Ziehau * PCI Express Error occured which is not described in PEX 3050*2d586421SSepherosa Ziehau * spec. 3051*2d586421SSepherosa Ziehau * This error is also mapped either to Master Abort( 3052*2d586421SSepherosa Ziehau * Y2_IS_MST_ERR) or Target Abort (Y2_IS_IRQ_STAT) bit and 3053*2d586421SSepherosa Ziehau * can only be cleared there. 3054*2d586421SSepherosa Ziehau */ 3055*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 3056*2d586421SSepherosa Ziehau "PCI Express protocol violation error\n"); 3057*2d586421SSepherosa Ziehau } 3058*2d586421SSepherosa Ziehau 3059*2d586421SSepherosa Ziehau if ((status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) { 3060*2d586421SSepherosa Ziehau uint16_t v16; 3061*2d586421SSepherosa Ziehau 3062*2d586421SSepherosa Ziehau if ((status & Y2_IS_MST_ERR) != 0) 3063*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 3064*2d586421SSepherosa Ziehau "unexpected IRQ Status error\n"); 3065*2d586421SSepherosa Ziehau else 3066*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 3067*2d586421SSepherosa Ziehau "unexpected IRQ Master error\n"); 3068*2d586421SSepherosa Ziehau /* Reset all bits in the PCI status register. */ 3069*2d586421SSepherosa Ziehau v16 = pci_read_config(sc->msk_dev, PCIR_STATUS, 2); 3070*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 3071*2d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_STATUS, v16 | 3072*2d586421SSepherosa Ziehau PCIM_STATUS_PERR | PCIM_STATUS_SERR | PCIM_STATUS_RMABORT | 3073*2d586421SSepherosa Ziehau PCIM_STATUS_RTABORT | PCIM_STATUS_PERRREPORT, 2); 3074*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 3075*2d586421SSepherosa Ziehau } 3076*2d586421SSepherosa Ziehau 3077*2d586421SSepherosa Ziehau /* Check for PCI Express Uncorrectable Error. */ 3078*2d586421SSepherosa Ziehau if ((status & Y2_IS_PCI_EXP) != 0) { 3079*2d586421SSepherosa Ziehau uint32_t v32; 3080*2d586421SSepherosa Ziehau 3081*2d586421SSepherosa Ziehau /* 3082*2d586421SSepherosa Ziehau * On PCI Express bus bridges are called root complexes (RC). 3083*2d586421SSepherosa Ziehau * PCI Express errors are recognized by the root complex too, 3084*2d586421SSepherosa Ziehau * which requests the system to handle the problem. After 3085*2d586421SSepherosa Ziehau * error occurence it may be that no access to the adapter 3086*2d586421SSepherosa Ziehau * may be performed any longer. 3087*2d586421SSepherosa Ziehau */ 3088*2d586421SSepherosa Ziehau 3089*2d586421SSepherosa Ziehau v32 = CSR_PCI_READ_4(sc, PEX_UNC_ERR_STAT); 3090*2d586421SSepherosa Ziehau if ((v32 & PEX_UNSUP_REQ) != 0) { 3091*2d586421SSepherosa Ziehau /* Ignore unsupported request error. */ 3092*2d586421SSepherosa Ziehau if (bootverbose) { 3093*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, 3094*2d586421SSepherosa Ziehau "Uncorrectable PCI Express error\n"); 3095*2d586421SSepherosa Ziehau } 3096*2d586421SSepherosa Ziehau } 3097*2d586421SSepherosa Ziehau if ((v32 & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) { 3098*2d586421SSepherosa Ziehau int i; 3099*2d586421SSepherosa Ziehau 3100*2d586421SSepherosa Ziehau /* Get TLP header form Log Registers. */ 3101*2d586421SSepherosa Ziehau for (i = 0; i < 4; i++) 3102*2d586421SSepherosa Ziehau tlphead[i] = CSR_PCI_READ_4(sc, 3103*2d586421SSepherosa Ziehau PEX_HEADER_LOG + i * 4); 3104*2d586421SSepherosa Ziehau /* Check for vendor defined broadcast message. */ 3105*2d586421SSepherosa Ziehau if (!(tlphead[0] == 0x73004001 && tlphead[1] == 0x7f)) { 3106*2d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_IS_PCI_EXP; 3107*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 3108*2d586421SSepherosa Ziehau sc->msk_intrhwemask); 3109*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 3110*2d586421SSepherosa Ziehau } 3111*2d586421SSepherosa Ziehau } 3112*2d586421SSepherosa Ziehau /* Clear the interrupt. */ 3113*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 3114*2d586421SSepherosa Ziehau CSR_PCI_WRITE_4(sc, PEX_UNC_ERR_STAT, 0xffffffff); 3115*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 3116*2d586421SSepherosa Ziehau } 3117*2d586421SSepherosa Ziehau 3118*2d586421SSepherosa Ziehau if ((status & Y2_HWE_L1_MASK) != 0 && sc->msk_if[MSK_PORT_A] != NULL) 3119*2d586421SSepherosa Ziehau msk_handle_hwerr(sc->msk_if[MSK_PORT_A], status); 3120*2d586421SSepherosa Ziehau if ((status & Y2_HWE_L2_MASK) != 0 && sc->msk_if[MSK_PORT_B] != NULL) 3121*2d586421SSepherosa Ziehau msk_handle_hwerr(sc->msk_if[MSK_PORT_B], status >> 8); 3122*2d586421SSepherosa Ziehau } 3123*2d586421SSepherosa Ziehau 3124*2d586421SSepherosa Ziehau static __inline void 3125*2d586421SSepherosa Ziehau msk_rxput(struct msk_if_softc *sc_if) 3126*2d586421SSepherosa Ziehau { 3127*2d586421SSepherosa Ziehau struct msk_softc *sc; 3128*2d586421SSepherosa Ziehau 3129*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 3130*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 3131*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) { 3132*2d586421SSepherosa Ziehau bus_dmamap_sync( 3133*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 3134*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 3135*2d586421SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 3136*2d586421SSepherosa Ziehau } else 3137*2d586421SSepherosa Ziehau #endif 3138*2d586421SSepherosa Ziehau { 3139*2d586421SSepherosa Ziehau bus_dmamap_sync( 3140*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_ring_tag, 3141*2d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_ring_map, 3142*2d586421SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 3143*2d586421SSepherosa Ziehau } 3144*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, Y2_PREF_Q_ADDR(sc_if->msk_rxq, 3145*2d586421SSepherosa Ziehau PREF_UNIT_PUT_IDX_REG), sc_if->msk_cdata.msk_rx_prod); 3146*2d586421SSepherosa Ziehau } 3147*2d586421SSepherosa Ziehau 3148*2d586421SSepherosa Ziehau static int 3149*2d586421SSepherosa Ziehau mskc_handle_events(struct msk_softc *sc) 3150*2d586421SSepherosa Ziehau { 3151*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 3152*2d586421SSepherosa Ziehau int rxput[2]; 3153*2d586421SSepherosa Ziehau struct msk_stat_desc *sd; 3154*2d586421SSepherosa Ziehau uint32_t control, status; 3155*2d586421SSepherosa Ziehau int cons, idx, len, port, rxprog; 3156*2d586421SSepherosa Ziehau 3157*2d586421SSepherosa Ziehau idx = CSR_READ_2(sc, STAT_PUT_IDX); 3158*2d586421SSepherosa Ziehau if (idx == sc->msk_stat_cons) 3159*2d586421SSepherosa Ziehau return (0); 3160*2d586421SSepherosa Ziehau 3161*2d586421SSepherosa Ziehau /* Sync status LEs. */ 3162*2d586421SSepherosa Ziehau bus_dmamap_sync(sc->msk_stat_tag, sc->msk_stat_map, 3163*2d586421SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 3164*2d586421SSepherosa Ziehau /* XXX Sync Rx LEs here. */ 3165*2d586421SSepherosa Ziehau 3166*2d586421SSepherosa Ziehau rxput[MSK_PORT_A] = rxput[MSK_PORT_B] = 0; 3167*2d586421SSepherosa Ziehau 3168*2d586421SSepherosa Ziehau rxprog = 0; 3169*2d586421SSepherosa Ziehau for (cons = sc->msk_stat_cons; cons != idx;) { 3170*2d586421SSepherosa Ziehau sd = &sc->msk_stat_ring[cons]; 3171*2d586421SSepherosa Ziehau control = le32toh(sd->msk_control); 3172*2d586421SSepherosa Ziehau if ((control & HW_OWNER) == 0) 3173*2d586421SSepherosa Ziehau break; 3174*2d586421SSepherosa Ziehau /* 3175*2d586421SSepherosa Ziehau * Marvell's FreeBSD driver updates status LE after clearing 3176*2d586421SSepherosa Ziehau * HW_OWNER. However we don't have a way to sync single LE 3177*2d586421SSepherosa Ziehau * with bus_dma(9) API. bus_dma(9) provides a way to sync 3178*2d586421SSepherosa Ziehau * an entire DMA map. So don't sync LE until we have a better 3179*2d586421SSepherosa Ziehau * way to sync LEs. 3180*2d586421SSepherosa Ziehau */ 3181*2d586421SSepherosa Ziehau control &= ~HW_OWNER; 3182*2d586421SSepherosa Ziehau sd->msk_control = htole32(control); 3183*2d586421SSepherosa Ziehau status = le32toh(sd->msk_status); 3184*2d586421SSepherosa Ziehau len = control & STLE_LEN_MASK; 3185*2d586421SSepherosa Ziehau port = (control >> 16) & 0x01; 3186*2d586421SSepherosa Ziehau sc_if = sc->msk_if[port]; 3187*2d586421SSepherosa Ziehau if (sc_if == NULL) { 3188*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, "invalid port opcode " 3189*2d586421SSepherosa Ziehau "0x%08x\n", control & STLE_OP_MASK); 3190*2d586421SSepherosa Ziehau continue; 3191*2d586421SSepherosa Ziehau } 3192*2d586421SSepherosa Ziehau 3193*2d586421SSepherosa Ziehau switch (control & STLE_OP_MASK) { 3194*2d586421SSepherosa Ziehau case OP_RXVLAN: 3195*2d586421SSepherosa Ziehau sc_if->msk_vtag = ntohs(len); 3196*2d586421SSepherosa Ziehau break; 3197*2d586421SSepherosa Ziehau case OP_RXCHKSVLAN: 3198*2d586421SSepherosa Ziehau sc_if->msk_vtag = ntohs(len); 3199*2d586421SSepherosa Ziehau break; 3200*2d586421SSepherosa Ziehau case OP_RXSTAT: 3201*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 3202*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) 3203*2d586421SSepherosa Ziehau msk_jumbo_rxeof(sc_if, status, len); 3204*2d586421SSepherosa Ziehau else 3205*2d586421SSepherosa Ziehau #endif 3206*2d586421SSepherosa Ziehau msk_rxeof(sc_if, status, len); 3207*2d586421SSepherosa Ziehau rxprog++; 3208*2d586421SSepherosa Ziehau /* 3209*2d586421SSepherosa Ziehau * Because there is no way to sync single Rx LE 3210*2d586421SSepherosa Ziehau * put the DMA sync operation off until the end of 3211*2d586421SSepherosa Ziehau * event processing. 3212*2d586421SSepherosa Ziehau */ 3213*2d586421SSepherosa Ziehau rxput[port]++; 3214*2d586421SSepherosa Ziehau /* Update prefetch unit if we've passed water mark. */ 3215*2d586421SSepherosa Ziehau if (rxput[port] >= sc_if->msk_cdata.msk_rx_putwm) { 3216*2d586421SSepherosa Ziehau msk_rxput(sc_if); 3217*2d586421SSepherosa Ziehau rxput[port] = 0; 3218*2d586421SSepherosa Ziehau } 3219*2d586421SSepherosa Ziehau break; 3220*2d586421SSepherosa Ziehau case OP_TXINDEXLE: 3221*2d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_A] != NULL) { 3222*2d586421SSepherosa Ziehau msk_txeof(sc->msk_if[MSK_PORT_A], 3223*2d586421SSepherosa Ziehau status & STLE_TXA1_MSKL); 3224*2d586421SSepherosa Ziehau } 3225*2d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_B] != NULL) { 3226*2d586421SSepherosa Ziehau msk_txeof(sc->msk_if[MSK_PORT_B], 3227*2d586421SSepherosa Ziehau ((status & STLE_TXA2_MSKL) >> 3228*2d586421SSepherosa Ziehau STLE_TXA2_SHIFTL) | 3229*2d586421SSepherosa Ziehau ((len & STLE_TXA2_MSKH) << 3230*2d586421SSepherosa Ziehau STLE_TXA2_SHIFTH)); 3231*2d586421SSepherosa Ziehau } 3232*2d586421SSepherosa Ziehau break; 3233*2d586421SSepherosa Ziehau default: 3234*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, "unhandled opcode 0x%08x\n", 3235*2d586421SSepherosa Ziehau control & STLE_OP_MASK); 3236*2d586421SSepherosa Ziehau break; 3237*2d586421SSepherosa Ziehau } 3238*2d586421SSepherosa Ziehau MSK_INC(cons, MSK_STAT_RING_CNT); 3239*2d586421SSepherosa Ziehau if (rxprog > sc->msk_process_limit) 3240*2d586421SSepherosa Ziehau break; 3241*2d586421SSepherosa Ziehau } 3242*2d586421SSepherosa Ziehau 3243*2d586421SSepherosa Ziehau sc->msk_stat_cons = cons; 3244*2d586421SSepherosa Ziehau /* XXX We should sync status LEs here. See above notes. */ 3245*2d586421SSepherosa Ziehau 3246*2d586421SSepherosa Ziehau if (rxput[MSK_PORT_A] > 0) 3247*2d586421SSepherosa Ziehau msk_rxput(sc->msk_if[MSK_PORT_A]); 3248*2d586421SSepherosa Ziehau if (rxput[MSK_PORT_B] > 0) 3249*2d586421SSepherosa Ziehau msk_rxput(sc->msk_if[MSK_PORT_B]); 3250*2d586421SSepherosa Ziehau 3251*2d586421SSepherosa Ziehau return (sc->msk_stat_cons != CSR_READ_2(sc, STAT_PUT_IDX)); 3252*2d586421SSepherosa Ziehau } 3253*2d586421SSepherosa Ziehau 3254*2d586421SSepherosa Ziehau /* Legacy interrupt handler for shared interrupt. */ 3255*2d586421SSepherosa Ziehau static void 3256*2d586421SSepherosa Ziehau mskc_intr(void *xsc) 3257*2d586421SSepherosa Ziehau { 3258*2d586421SSepherosa Ziehau struct msk_softc *sc; 3259*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if0, *sc_if1; 3260*2d586421SSepherosa Ziehau struct ifnet *ifp0, *ifp1; 3261*2d586421SSepherosa Ziehau uint32_t status; 3262*2d586421SSepherosa Ziehau 3263*2d586421SSepherosa Ziehau sc = xsc; 3264*2d586421SSepherosa Ziehau ASSERT_SERIALIZED(&sc->msk_serializer); 3265*2d586421SSepherosa Ziehau 3266*2d586421SSepherosa Ziehau /* Reading B0_Y2_SP_ISRC2 masks further interrupts. */ 3267*2d586421SSepherosa Ziehau status = CSR_READ_4(sc, B0_Y2_SP_ISRC2); 3268*2d586421SSepherosa Ziehau if (status == 0 || status == 0xffffffff || sc->msk_suspended != 0 || 3269*2d586421SSepherosa Ziehau (status & sc->msk_intrmask) == 0) { 3270*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); 3271*2d586421SSepherosa Ziehau return; 3272*2d586421SSepherosa Ziehau } 3273*2d586421SSepherosa Ziehau 3274*2d586421SSepherosa Ziehau sc_if0 = sc->msk_if[MSK_PORT_A]; 3275*2d586421SSepherosa Ziehau sc_if1 = sc->msk_if[MSK_PORT_B]; 3276*2d586421SSepherosa Ziehau ifp0 = ifp1 = NULL; 3277*2d586421SSepherosa Ziehau if (sc_if0 != NULL) 3278*2d586421SSepherosa Ziehau ifp0 = sc_if0->msk_ifp; 3279*2d586421SSepherosa Ziehau if (sc_if1 != NULL) 3280*2d586421SSepherosa Ziehau ifp1 = sc_if1->msk_ifp; 3281*2d586421SSepherosa Ziehau 3282*2d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_PHY1) != 0 && sc_if0 != NULL) 3283*2d586421SSepherosa Ziehau msk_intr_phy(sc_if0); 3284*2d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_PHY2) != 0 && sc_if1 != NULL) 3285*2d586421SSepherosa Ziehau msk_intr_phy(sc_if1); 3286*2d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_MAC1) != 0 && sc_if0 != NULL) 3287*2d586421SSepherosa Ziehau msk_intr_gmac(sc_if0); 3288*2d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_MAC2) != 0 && sc_if1 != NULL) 3289*2d586421SSepherosa Ziehau msk_intr_gmac(sc_if1); 3290*2d586421SSepherosa Ziehau if ((status & (Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2)) != 0) { 3291*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, "Rx descriptor error\n"); 3292*2d586421SSepherosa Ziehau sc->msk_intrmask &= ~(Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2); 3293*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 3294*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 3295*2d586421SSepherosa Ziehau } 3296*2d586421SSepherosa Ziehau if ((status & (Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2)) != 0) { 3297*2d586421SSepherosa Ziehau device_printf(sc->msk_dev, "Tx descriptor error\n"); 3298*2d586421SSepherosa Ziehau sc->msk_intrmask &= ~(Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2); 3299*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 3300*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 3301*2d586421SSepherosa Ziehau } 3302*2d586421SSepherosa Ziehau if ((status & Y2_IS_HW_ERR) != 0) 3303*2d586421SSepherosa Ziehau mskc_intr_hwerr(sc); 3304*2d586421SSepherosa Ziehau 3305*2d586421SSepherosa Ziehau while (mskc_handle_events(sc) != 0) 3306*2d586421SSepherosa Ziehau ; 3307*2d586421SSepherosa Ziehau if ((status & Y2_IS_STAT_BMU) != 0) 3308*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ); 3309*2d586421SSepherosa Ziehau 3310*2d586421SSepherosa Ziehau /* Reenable interrupts. */ 3311*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); 3312*2d586421SSepherosa Ziehau 3313*2d586421SSepherosa Ziehau if (ifp0 != NULL && (ifp0->if_flags & IFF_RUNNING) != 0 && 3314*2d586421SSepherosa Ziehau !ifq_is_empty(&ifp0->if_snd)) 3315*2d586421SSepherosa Ziehau ifp0->if_start(ifp0); 3316*2d586421SSepherosa Ziehau if (ifp1 != NULL && (ifp1->if_flags & IFF_RUNNING) != 0 && 3317*2d586421SSepherosa Ziehau !ifq_is_empty(&ifp1->if_snd)) 3318*2d586421SSepherosa Ziehau ifp1->if_start(ifp1); 3319*2d586421SSepherosa Ziehau } 3320*2d586421SSepherosa Ziehau 3321*2d586421SSepherosa Ziehau static void 3322*2d586421SSepherosa Ziehau msk_init(void *xsc) 3323*2d586421SSepherosa Ziehau { 3324*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = xsc; 3325*2d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 3326*2d586421SSepherosa Ziehau struct ifnet *ifp = sc_if->msk_ifp; 3327*2d586421SSepherosa Ziehau struct mii_data *mii; 3328*2d586421SSepherosa Ziehau uint16_t eaddr[ETHER_ADDR_LEN / 2]; 3329*2d586421SSepherosa Ziehau uint16_t gmac; 3330*2d586421SSepherosa Ziehau int error, i; 3331*2d586421SSepherosa Ziehau 3332*2d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 3333*2d586421SSepherosa Ziehau 3334*2d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 3335*2d586421SSepherosa Ziehau 3336*2d586421SSepherosa Ziehau error = 0; 3337*2d586421SSepherosa Ziehau /* Cancel pending I/O and free all Rx/Tx buffers. */ 3338*2d586421SSepherosa Ziehau msk_stop(sc_if); 3339*2d586421SSepherosa Ziehau 3340*2d586421SSepherosa Ziehau sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + EVL_ENCAPLEN; 3341*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && 3342*2d586421SSepherosa Ziehau sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 3343*2d586421SSepherosa Ziehau /* 3344*2d586421SSepherosa Ziehau * In Yukon EC Ultra, TSO & checksum offload is not 3345*2d586421SSepherosa Ziehau * supported for jumbo frame. 3346*2d586421SSepherosa Ziehau */ 3347*2d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 3348*2d586421SSepherosa Ziehau ifp->if_capenable &= ~IFCAP_TXCSUM; 3349*2d586421SSepherosa Ziehau } 3350*2d586421SSepherosa Ziehau 3351*2d586421SSepherosa Ziehau /* 3352*2d586421SSepherosa Ziehau * Initialize GMAC first. 3353*2d586421SSepherosa Ziehau * Without this initialization, Rx MAC did not work as expected 3354*2d586421SSepherosa Ziehau * and Rx MAC garbled status LEs and it resulted in out-of-order 3355*2d586421SSepherosa Ziehau * or duplicated frame delivery which in turn showed very poor 3356*2d586421SSepherosa Ziehau * Rx performance.(I had to write a packet analysis code that 3357*2d586421SSepherosa Ziehau * could be embeded in driver to diagnose this issue.) 3358*2d586421SSepherosa Ziehau * I've spent almost 2 months to fix this issue. If I have had 3359*2d586421SSepherosa Ziehau * datasheet for Yukon II I wouldn't have encountered this. :-( 3360*2d586421SSepherosa Ziehau */ 3361*2d586421SSepherosa Ziehau gmac = GM_GPCR_SPEED_100 | GM_GPCR_SPEED_1000 | GM_GPCR_DUP_FULL; 3362*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac); 3363*2d586421SSepherosa Ziehau 3364*2d586421SSepherosa Ziehau /* Dummy read the Interrupt Source Register. */ 3365*2d586421SSepherosa Ziehau CSR_READ_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_SRC)); 3366*2d586421SSepherosa Ziehau 3367*2d586421SSepherosa Ziehau /* Set MIB Clear Counter Mode. */ 3368*2d586421SSepherosa Ziehau gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_PHY_ADDR); 3369*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac | GM_PAR_MIB_CLR); 3370*2d586421SSepherosa Ziehau /* Read all MIB Counters with Clear Mode set. */ 3371*2d586421SSepherosa Ziehau for (i = 0; i < GM_MIB_CNT_SIZE; i++) 3372*2d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_MIB_CNT_BASE + 8 * i); 3373*2d586421SSepherosa Ziehau /* Clear MIB Clear Counter Mode. */ 3374*2d586421SSepherosa Ziehau gmac &= ~GM_PAR_MIB_CLR; 3375*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac); 3376*2d586421SSepherosa Ziehau 3377*2d586421SSepherosa Ziehau /* Disable FCS. */ 3378*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, GM_RXCR_CRC_DIS); 3379*2d586421SSepherosa Ziehau 3380*2d586421SSepherosa Ziehau /* Setup Transmit Control Register. */ 3381*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); 3382*2d586421SSepherosa Ziehau 3383*2d586421SSepherosa Ziehau /* Setup Transmit Flow Control Register. */ 3384*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_FLOW_CTRL, 0xffff); 3385*2d586421SSepherosa Ziehau 3386*2d586421SSepherosa Ziehau /* Setup Transmit Parameter Register. */ 3387*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_PARAM, 3388*2d586421SSepherosa Ziehau TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | 3389*2d586421SSepherosa Ziehau TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) | TX_BACK_OFF_LIM(TX_BOF_LIM_DEF)); 3390*2d586421SSepherosa Ziehau 3391*2d586421SSepherosa Ziehau gmac = DATA_BLIND_VAL(DATA_BLIND_DEF) | 3392*2d586421SSepherosa Ziehau GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); 3393*2d586421SSepherosa Ziehau 3394*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN) 3395*2d586421SSepherosa Ziehau gmac |= GM_SMOD_JUMBO_ENA; 3396*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SERIAL_MODE, gmac); 3397*2d586421SSepherosa Ziehau 3398*2d586421SSepherosa Ziehau /* Set station address. */ 3399*2d586421SSepherosa Ziehau bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); 3400*2d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN /2; i++) 3401*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1L + i * 4, 3402*2d586421SSepherosa Ziehau eaddr[i]); 3403*2d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN /2; i++) 3404*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2L + i * 4, 3405*2d586421SSepherosa Ziehau eaddr[i]); 3406*2d586421SSepherosa Ziehau 3407*2d586421SSepherosa Ziehau /* Disable interrupts for counter overflows. */ 3408*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_IRQ_MSK, 0); 3409*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_IRQ_MSK, 0); 3410*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TR_IRQ_MSK, 0); 3411*2d586421SSepherosa Ziehau 3412*2d586421SSepherosa Ziehau /* Configure Rx MAC FIFO. */ 3413*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_SET); 3414*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_CLR); 3415*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 3416*2d586421SSepherosa Ziehau GMF_OPER_ON | GMF_RX_F_FL_ON); 3417*2d586421SSepherosa Ziehau 3418*2d586421SSepherosa Ziehau /* Set promiscuous mode. */ 3419*2d586421SSepherosa Ziehau msk_setpromisc(sc_if); 3420*2d586421SSepherosa Ziehau 3421*2d586421SSepherosa Ziehau /* Set multicast filter. */ 3422*2d586421SSepherosa Ziehau msk_setmulti(sc_if); 3423*2d586421SSepherosa Ziehau 3424*2d586421SSepherosa Ziehau /* Flush Rx MAC FIFO on any flow control or error. */ 3425*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK), 3426*2d586421SSepherosa Ziehau GMR_FS_ANY_ERR); 3427*2d586421SSepherosa Ziehau 3428*2d586421SSepherosa Ziehau /* Set Rx FIFO flush threshold to 64 bytes. */ 3429*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR), 3430*2d586421SSepherosa Ziehau RX_GMF_FL_THR_DEF); 3431*2d586421SSepherosa Ziehau 3432*2d586421SSepherosa Ziehau /* Configure Tx MAC FIFO. */ 3433*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET); 3434*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_CLR); 3435*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_OPER_ON); 3436*2d586421SSepherosa Ziehau 3437*2d586421SSepherosa Ziehau /* Configure hardware VLAN tag insertion/stripping. */ 3438*2d586421SSepherosa Ziehau msk_setvlan(sc_if, ifp); 3439*2d586421SSepherosa Ziehau 3440*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 3441*2d586421SSepherosa Ziehau /* Set Rx Pause threshould. */ 3442*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR), 3443*2d586421SSepherosa Ziehau MSK_ECU_LLPP); 3444*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), 3445*2d586421SSepherosa Ziehau MSK_ECU_ULPP); 3446*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN) { 3447*2d586421SSepherosa Ziehau /* 3448*2d586421SSepherosa Ziehau * Set Tx GMAC FIFO Almost Empty Threshold. 3449*2d586421SSepherosa Ziehau */ 3450*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_AE_THR), 3451*2d586421SSepherosa Ziehau MSK_ECU_JUMBO_WM << 16 | MSK_ECU_AE_THR); 3452*2d586421SSepherosa Ziehau /* Disable Store & Forward mode for Tx. */ 3453*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 3454*2d586421SSepherosa Ziehau TX_JUMBO_ENA | TX_STFW_DIS); 3455*2d586421SSepherosa Ziehau } else { 3456*2d586421SSepherosa Ziehau /* Enable Store & Forward mode for Tx. */ 3457*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 3458*2d586421SSepherosa Ziehau TX_JUMBO_DIS | TX_STFW_ENA); 3459*2d586421SSepherosa Ziehau } 3460*2d586421SSepherosa Ziehau } 3461*2d586421SSepherosa Ziehau 3462*2d586421SSepherosa Ziehau /* 3463*2d586421SSepherosa Ziehau * Disable Force Sync bit and Alloc bit in Tx RAM interface 3464*2d586421SSepherosa Ziehau * arbiter as we don't use Sync Tx queue. 3465*2d586421SSepherosa Ziehau */ 3466*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), 3467*2d586421SSepherosa Ziehau TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); 3468*2d586421SSepherosa Ziehau /* Enable the RAM Interface Arbiter. */ 3469*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), TXA_ENA_ARB); 3470*2d586421SSepherosa Ziehau 3471*2d586421SSepherosa Ziehau /* Setup RAM buffer. */ 3472*2d586421SSepherosa Ziehau msk_set_rambuffer(sc_if); 3473*2d586421SSepherosa Ziehau 3474*2d586421SSepherosa Ziehau /* Disable Tx sync Queue. */ 3475*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txsq, RB_CTRL), RB_RST_SET); 3476*2d586421SSepherosa Ziehau 3477*2d586421SSepherosa Ziehau /* Setup Tx Queue Bus Memory Interface. */ 3478*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_CLR_RESET); 3479*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_OPER_INIT); 3480*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_FIFO_OP_ON); 3481*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_WM), MSK_BMU_TX_WM); 3482*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U && 3483*2d586421SSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_EC_U_A0) { 3484*2d586421SSepherosa Ziehau /* Fix for Yukon-EC Ultra: set BMU FIFO level */ 3485*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_AL), MSK_ECU_TXFF_LEV); 3486*2d586421SSepherosa Ziehau } 3487*2d586421SSepherosa Ziehau 3488*2d586421SSepherosa Ziehau /* Setup Rx Queue Bus Memory Interface. */ 3489*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_CLR_RESET); 3490*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_OPER_INIT); 3491*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_FIFO_OP_ON); 3492*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_rxq, Q_WM), MSK_BMU_RX_WM); 3493*2d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U && 3494*2d586421SSepherosa Ziehau sc->msk_hw_rev >= CHIP_REV_YU_EC_U_A1) { 3495*2d586421SSepherosa Ziehau /* MAC Rx RAM Read is controlled by hardware. */ 3496*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_F), F_M_RX_RAM_DIS); 3497*2d586421SSepherosa Ziehau } 3498*2d586421SSepherosa Ziehau 3499*2d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_txq, 3500*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_tx_ring_paddr, MSK_TX_RING_CNT - 1); 3501*2d586421SSepherosa Ziehau msk_init_tx_ring(sc_if); 3502*2d586421SSepherosa Ziehau 3503*2d586421SSepherosa Ziehau /* Disable Rx checksum offload and RSS hash. */ 3504*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), 3505*2d586421SSepherosa Ziehau BMU_DIS_RX_CHKSUM | BMU_DIS_RX_RSS_HASH); 3506*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 3507*2d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) { 3508*2d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_rxq, 3509*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring_paddr, 3510*2d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_CNT - 1); 3511*2d586421SSepherosa Ziehau error = msk_init_jumbo_rx_ring(sc_if); 3512*2d586421SSepherosa Ziehau } else 3513*2d586421SSepherosa Ziehau #endif 3514*2d586421SSepherosa Ziehau { 3515*2d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_rxq, 3516*2d586421SSepherosa Ziehau sc_if->msk_rdata.msk_rx_ring_paddr, 3517*2d586421SSepherosa Ziehau MSK_RX_RING_CNT - 1); 3518*2d586421SSepherosa Ziehau error = msk_init_rx_ring(sc_if); 3519*2d586421SSepherosa Ziehau } 3520*2d586421SSepherosa Ziehau if (error != 0) { 3521*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 3522*2d586421SSepherosa Ziehau "initialization failed: no memory for Rx buffers\n"); 3523*2d586421SSepherosa Ziehau msk_stop(sc_if); 3524*2d586421SSepherosa Ziehau return; 3525*2d586421SSepherosa Ziehau } 3526*2d586421SSepherosa Ziehau 3527*2d586421SSepherosa Ziehau /* Configure interrupt handling. */ 3528*2d586421SSepherosa Ziehau if (sc_if->msk_port == MSK_PORT_A) { 3529*2d586421SSepherosa Ziehau sc->msk_intrmask |= Y2_IS_PORT_A; 3530*2d586421SSepherosa Ziehau sc->msk_intrhwemask |= Y2_HWE_L1_MASK; 3531*2d586421SSepherosa Ziehau } else { 3532*2d586421SSepherosa Ziehau sc->msk_intrmask |= Y2_IS_PORT_B; 3533*2d586421SSepherosa Ziehau sc->msk_intrhwemask |= Y2_HWE_L2_MASK; 3534*2d586421SSepherosa Ziehau } 3535*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask); 3536*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 3537*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 3538*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 3539*2d586421SSepherosa Ziehau 3540*2d586421SSepherosa Ziehau sc_if->msk_link = 0; 3541*2d586421SSepherosa Ziehau mii_mediachg(mii); 3542*2d586421SSepherosa Ziehau 3543*2d586421SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 3544*2d586421SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 3545*2d586421SSepherosa Ziehau 3546*2d586421SSepherosa Ziehau callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if); 3547*2d586421SSepherosa Ziehau } 3548*2d586421SSepherosa Ziehau 3549*2d586421SSepherosa Ziehau static void 3550*2d586421SSepherosa Ziehau msk_set_rambuffer(struct msk_if_softc *sc_if) 3551*2d586421SSepherosa Ziehau { 3552*2d586421SSepherosa Ziehau struct msk_softc *sc; 3553*2d586421SSepherosa Ziehau int ltpp, utpp; 3554*2d586421SSepherosa Ziehau 3555*2d586421SSepherosa Ziehau sc = sc_if->msk_softc; 3556*2d586421SSepherosa Ziehau 3557*2d586421SSepherosa Ziehau /* Setup Rx Queue. */ 3558*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_CLR); 3559*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_START), 3560*2d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 3561*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_END), 3562*2d586421SSepherosa Ziehau sc->msk_rxqend[sc_if->msk_port] / 8); 3563*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_WP), 3564*2d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 3565*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RP), 3566*2d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 3567*2d586421SSepherosa Ziehau 3568*2d586421SSepherosa Ziehau utpp = (sc->msk_rxqend[sc_if->msk_port] + 1 - 3569*2d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] - MSK_RB_ULPP) / 8; 3570*2d586421SSepherosa Ziehau ltpp = (sc->msk_rxqend[sc_if->msk_port] + 1 - 3571*2d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] - MSK_RB_LLPP_B) / 8; 3572*2d586421SSepherosa Ziehau if (sc->msk_rxqsize < MSK_MIN_RXQ_SIZE) 3573*2d586421SSepherosa Ziehau ltpp += (MSK_RB_LLPP_B - MSK_RB_LLPP_S) / 8; 3574*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RX_UTPP), utpp); 3575*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RX_LTPP), ltpp); 3576*2d586421SSepherosa Ziehau /* Set Rx priority(RB_RX_UTHP/RB_RX_LTHP) thresholds? */ 3577*2d586421SSepherosa Ziehau 3578*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_ENA_OP_MD); 3579*2d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL)); 3580*2d586421SSepherosa Ziehau 3581*2d586421SSepherosa Ziehau /* Setup Tx Queue. */ 3582*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_RST_CLR); 3583*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_START), 3584*2d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 3585*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_END), 3586*2d586421SSepherosa Ziehau sc->msk_txqend[sc_if->msk_port] / 8); 3587*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_WP), 3588*2d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 3589*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_RP), 3590*2d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 3591*2d586421SSepherosa Ziehau /* Enable Store & Forward for Tx side. */ 3592*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_ENA_STFWD); 3593*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_ENA_OP_MD); 3594*2d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL)); 3595*2d586421SSepherosa Ziehau } 3596*2d586421SSepherosa Ziehau 3597*2d586421SSepherosa Ziehau static void 3598*2d586421SSepherosa Ziehau msk_set_prefetch(struct msk_softc *sc, int qaddr, bus_addr_t addr, 3599*2d586421SSepherosa Ziehau uint32_t count) 3600*2d586421SSepherosa Ziehau { 3601*2d586421SSepherosa Ziehau 3602*2d586421SSepherosa Ziehau /* Reset the prefetch unit. */ 3603*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 3604*2d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 3605*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 3606*2d586421SSepherosa Ziehau PREF_UNIT_RST_CLR); 3607*2d586421SSepherosa Ziehau /* Set LE base address. */ 3608*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_ADDR_LOW_REG), 3609*2d586421SSepherosa Ziehau MSK_ADDR_LO(addr)); 3610*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_ADDR_HI_REG), 3611*2d586421SSepherosa Ziehau MSK_ADDR_HI(addr)); 3612*2d586421SSepherosa Ziehau /* Set the list last index. */ 3613*2d586421SSepherosa Ziehau CSR_WRITE_2(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_LAST_IDX_REG), 3614*2d586421SSepherosa Ziehau count); 3615*2d586421SSepherosa Ziehau /* Turn on prefetch unit. */ 3616*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 3617*2d586421SSepherosa Ziehau PREF_UNIT_OP_ON); 3618*2d586421SSepherosa Ziehau /* Dummy read to ensure write. */ 3619*2d586421SSepherosa Ziehau CSR_READ_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG)); 3620*2d586421SSepherosa Ziehau } 3621*2d586421SSepherosa Ziehau 3622*2d586421SSepherosa Ziehau static void 3623*2d586421SSepherosa Ziehau msk_stop(struct msk_if_softc *sc_if) 3624*2d586421SSepherosa Ziehau { 3625*2d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 3626*2d586421SSepherosa Ziehau struct ifnet *ifp = sc_if->msk_ifp; 3627*2d586421SSepherosa Ziehau struct msk_txdesc *txd; 3628*2d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 3629*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 3630*2d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 3631*2d586421SSepherosa Ziehau #endif 3632*2d586421SSepherosa Ziehau uint32_t val; 3633*2d586421SSepherosa Ziehau int i; 3634*2d586421SSepherosa Ziehau 3635*2d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 3636*2d586421SSepherosa Ziehau 3637*2d586421SSepherosa Ziehau callout_stop(&sc_if->msk_tick_ch); 3638*2d586421SSepherosa Ziehau ifp->if_timer = 0; 3639*2d586421SSepherosa Ziehau 3640*2d586421SSepherosa Ziehau /* Disable interrupts. */ 3641*2d586421SSepherosa Ziehau if (sc_if->msk_port == MSK_PORT_A) { 3642*2d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_PORT_A; 3643*2d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_HWE_L1_MASK; 3644*2d586421SSepherosa Ziehau } else { 3645*2d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_PORT_B; 3646*2d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_HWE_L2_MASK; 3647*2d586421SSepherosa Ziehau } 3648*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask); 3649*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 3650*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 3651*2d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 3652*2d586421SSepherosa Ziehau 3653*2d586421SSepherosa Ziehau /* Disable Tx/Rx MAC. */ 3654*2d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 3655*2d586421SSepherosa Ziehau val &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); 3656*2d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, val); 3657*2d586421SSepherosa Ziehau /* Read again to ensure writing. */ 3658*2d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 3659*2d586421SSepherosa Ziehau 3660*2d586421SSepherosa Ziehau /* Stop Tx BMU. */ 3661*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_STOP); 3662*2d586421SSepherosa Ziehau val = CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); 3663*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 3664*2d586421SSepherosa Ziehau if ((val & (BMU_STOP | BMU_IDLE)) == 0) { 3665*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), 3666*2d586421SSepherosa Ziehau BMU_STOP); 3667*2d586421SSepherosa Ziehau CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); 3668*2d586421SSepherosa Ziehau } else 3669*2d586421SSepherosa Ziehau break; 3670*2d586421SSepherosa Ziehau DELAY(1); 3671*2d586421SSepherosa Ziehau } 3672*2d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 3673*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx BMU stop failed\n"); 3674*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), 3675*2d586421SSepherosa Ziehau RB_RST_SET | RB_DIS_OP_MD); 3676*2d586421SSepherosa Ziehau 3677*2d586421SSepherosa Ziehau /* Disable all GMAC interrupt. */ 3678*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK), 0); 3679*2d586421SSepherosa Ziehau /* Disable PHY interrupt. */ 3680*2d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_MASK, 0); 3681*2d586421SSepherosa Ziehau 3682*2d586421SSepherosa Ziehau /* Disable the RAM Interface Arbiter. */ 3683*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), TXA_DIS_ARB); 3684*2d586421SSepherosa Ziehau 3685*2d586421SSepherosa Ziehau /* Reset the PCI FIFO of the async Tx queue */ 3686*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), 3687*2d586421SSepherosa Ziehau BMU_RST_SET | BMU_FIFO_RST); 3688*2d586421SSepherosa Ziehau 3689*2d586421SSepherosa Ziehau /* Reset the Tx prefetch units. */ 3690*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(sc_if->msk_txq, PREF_UNIT_CTRL_REG), 3691*2d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 3692*2d586421SSepherosa Ziehau 3693*2d586421SSepherosa Ziehau /* Reset the RAM Buffer async Tx queue. */ 3694*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_RST_SET); 3695*2d586421SSepherosa Ziehau 3696*2d586421SSepherosa Ziehau /* Reset Tx MAC FIFO. */ 3697*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET); 3698*2d586421SSepherosa Ziehau /* Set Pause Off. */ 3699*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_PAUSE_OFF); 3700*2d586421SSepherosa Ziehau 3701*2d586421SSepherosa Ziehau /* 3702*2d586421SSepherosa Ziehau * The Rx Stop command will not work for Yukon-2 if the BMU does not 3703*2d586421SSepherosa Ziehau * reach the end of packet and since we can't make sure that we have 3704*2d586421SSepherosa Ziehau * incoming data, we must reset the BMU while it is not during a DMA 3705*2d586421SSepherosa Ziehau * transfer. Since it is possible that the Rx path is still active, 3706*2d586421SSepherosa Ziehau * the Rx RAM buffer will be stopped first, so any possible incoming 3707*2d586421SSepherosa Ziehau * data will not trigger a DMA. After the RAM buffer is stopped, the 3708*2d586421SSepherosa Ziehau * BMU is polled until any DMA in progress is ended and only then it 3709*2d586421SSepherosa Ziehau * will be reset. 3710*2d586421SSepherosa Ziehau */ 3711*2d586421SSepherosa Ziehau 3712*2d586421SSepherosa Ziehau /* Disable the RAM Buffer receive queue. */ 3713*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_DIS_OP_MD); 3714*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 3715*2d586421SSepherosa Ziehau if (CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, Q_RSL)) == 3716*2d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, Q_RL))) 3717*2d586421SSepherosa Ziehau break; 3718*2d586421SSepherosa Ziehau DELAY(1); 3719*2d586421SSepherosa Ziehau } 3720*2d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 3721*2d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Rx BMU stop failed\n"); 3722*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), 3723*2d586421SSepherosa Ziehau BMU_RST_SET | BMU_FIFO_RST); 3724*2d586421SSepherosa Ziehau /* Reset the Rx prefetch unit. */ 3725*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_CTRL_REG), 3726*2d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 3727*2d586421SSepherosa Ziehau /* Reset the RAM Buffer receive queue. */ 3728*2d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_SET); 3729*2d586421SSepherosa Ziehau /* Reset Rx MAC FIFO. */ 3730*2d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_SET); 3731*2d586421SSepherosa Ziehau 3732*2d586421SSepherosa Ziehau /* Free Rx and Tx mbufs still in the queues. */ 3733*2d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 3734*2d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 3735*2d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 3736*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_rx_tag, 3737*2d586421SSepherosa Ziehau rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 3738*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_rx_tag, 3739*2d586421SSepherosa Ziehau rxd->rx_dmamap); 3740*2d586421SSepherosa Ziehau m_freem(rxd->rx_m); 3741*2d586421SSepherosa Ziehau rxd->rx_m = NULL; 3742*2d586421SSepherosa Ziehau } 3743*2d586421SSepherosa Ziehau } 3744*2d586421SSepherosa Ziehau #ifdef MSK_JUMBO 3745*2d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 3746*2d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 3747*2d586421SSepherosa Ziehau if (jrxd->rx_m != NULL) { 3748*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, 3749*2d586421SSepherosa Ziehau jrxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 3750*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_tag, 3751*2d586421SSepherosa Ziehau jrxd->rx_dmamap); 3752*2d586421SSepherosa Ziehau m_freem(jrxd->rx_m); 3753*2d586421SSepherosa Ziehau jrxd->rx_m = NULL; 3754*2d586421SSepherosa Ziehau } 3755*2d586421SSepherosa Ziehau } 3756*2d586421SSepherosa Ziehau #endif 3757*2d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 3758*2d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 3759*2d586421SSepherosa Ziehau if (txd->tx_m != NULL) { 3760*2d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_tag, 3761*2d586421SSepherosa Ziehau txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); 3762*2d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, 3763*2d586421SSepherosa Ziehau txd->tx_dmamap); 3764*2d586421SSepherosa Ziehau m_freem(txd->tx_m); 3765*2d586421SSepherosa Ziehau txd->tx_m = NULL; 3766*2d586421SSepherosa Ziehau } 3767*2d586421SSepherosa Ziehau } 3768*2d586421SSepherosa Ziehau 3769*2d586421SSepherosa Ziehau /* 3770*2d586421SSepherosa Ziehau * Mark the interface down. 3771*2d586421SSepherosa Ziehau */ 3772*2d586421SSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 3773*2d586421SSepherosa Ziehau sc_if->msk_link = 0; 3774*2d586421SSepherosa Ziehau } 3775*2d586421SSepherosa Ziehau 3776*2d586421SSepherosa Ziehau #ifdef notyet 3777*2d586421SSepherosa Ziehau 3778*2d586421SSepherosa Ziehau static int 3779*2d586421SSepherosa Ziehau sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high) 3780*2d586421SSepherosa Ziehau { 3781*2d586421SSepherosa Ziehau int error, value; 3782*2d586421SSepherosa Ziehau 3783*2d586421SSepherosa Ziehau if (!arg1) 3784*2d586421SSepherosa Ziehau return (EINVAL); 3785*2d586421SSepherosa Ziehau value = *(int *)arg1; 3786*2d586421SSepherosa Ziehau error = sysctl_handle_int(oidp, &value, 0, req); 3787*2d586421SSepherosa Ziehau if (error || !req->newptr) 3788*2d586421SSepherosa Ziehau return (error); 3789*2d586421SSepherosa Ziehau if (value < low || value > high) 3790*2d586421SSepherosa Ziehau return (EINVAL); 3791*2d586421SSepherosa Ziehau *(int *)arg1 = value; 3792*2d586421SSepherosa Ziehau 3793*2d586421SSepherosa Ziehau return (0); 3794*2d586421SSepherosa Ziehau } 3795*2d586421SSepherosa Ziehau 3796*2d586421SSepherosa Ziehau static int 3797*2d586421SSepherosa Ziehau sysctl_hw_msk_proc_limit(SYSCTL_HANDLER_ARGS) 3798*2d586421SSepherosa Ziehau { 3799*2d586421SSepherosa Ziehau 3800*2d586421SSepherosa Ziehau return (sysctl_int_range(oidp, arg1, arg2, req, MSK_PROC_MIN, 3801*2d586421SSepherosa Ziehau MSK_PROC_MAX)); 3802*2d586421SSepherosa Ziehau } 3803*2d586421SSepherosa Ziehau 3804*2d586421SSepherosa Ziehau #endif 3805*2d586421SSepherosa Ziehau 3806*2d586421SSepherosa Ziehau static int 3807*2d586421SSepherosa Ziehau msk_dmamem_create(device_t dev, bus_size_t size, bus_dma_tag_t *dtag, 3808*2d586421SSepherosa Ziehau void **addr, bus_addr_t *paddr, bus_dmamap_t *dmap) 3809*2d586421SSepherosa Ziehau { 3810*2d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 3811*2d586421SSepherosa Ziehau struct msk_dmamap_arg ctx; 3812*2d586421SSepherosa Ziehau bus_dma_segment_t seg; 3813*2d586421SSepherosa Ziehau int error; 3814*2d586421SSepherosa Ziehau 3815*2d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag, 3816*2d586421SSepherosa Ziehau MSK_RING_ALIGN, 0, 3817*2d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 3818*2d586421SSepherosa Ziehau NULL, NULL, 3819*2d586421SSepherosa Ziehau size, 1, BUS_SPACE_MAXSIZE_32BIT, 3820*2d586421SSepherosa Ziehau 0, dtag); 3821*2d586421SSepherosa Ziehau if (error) { 3822*2d586421SSepherosa Ziehau device_printf(dev, "can't create DMA tag\n"); 3823*2d586421SSepherosa Ziehau return error; 3824*2d586421SSepherosa Ziehau } 3825*2d586421SSepherosa Ziehau 3826*2d586421SSepherosa Ziehau error = bus_dmamem_alloc(*dtag, addr, BUS_DMA_WAITOK | BUS_DMA_ZERO, 3827*2d586421SSepherosa Ziehau dmap); 3828*2d586421SSepherosa Ziehau if (error) { 3829*2d586421SSepherosa Ziehau device_printf(dev, "can't allocate DMA mem\n"); 3830*2d586421SSepherosa Ziehau bus_dma_tag_destroy(*dtag); 3831*2d586421SSepherosa Ziehau *dtag = NULL; 3832*2d586421SSepherosa Ziehau return error; 3833*2d586421SSepherosa Ziehau } 3834*2d586421SSepherosa Ziehau 3835*2d586421SSepherosa Ziehau bzero(&ctx, sizeof(ctx)); 3836*2d586421SSepherosa Ziehau ctx.nseg = 1; 3837*2d586421SSepherosa Ziehau ctx.segs = &seg; 3838*2d586421SSepherosa Ziehau error = bus_dmamap_load(*dtag, *dmap, *addr, size, 3839*2d586421SSepherosa Ziehau msk_dmamap_cb, &ctx, BUS_DMA_WAITOK); 3840*2d586421SSepherosa Ziehau if (error) { 3841*2d586421SSepherosa Ziehau device_printf(dev, "can't load DMA mem\n"); 3842*2d586421SSepherosa Ziehau bus_dmamem_free(*dtag, *addr, *dmap); 3843*2d586421SSepherosa Ziehau bus_dma_tag_destroy(*dtag); 3844*2d586421SSepherosa Ziehau *dtag = NULL; 3845*2d586421SSepherosa Ziehau return error; 3846*2d586421SSepherosa Ziehau } 3847*2d586421SSepherosa Ziehau *paddr = seg.ds_addr; 3848*2d586421SSepherosa Ziehau return 0; 3849*2d586421SSepherosa Ziehau } 3850*2d586421SSepherosa Ziehau 3851*2d586421SSepherosa Ziehau static void 3852*2d586421SSepherosa Ziehau msk_dmamem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap) 3853*2d586421SSepherosa Ziehau { 3854*2d586421SSepherosa Ziehau if (dtag != NULL) { 3855*2d586421SSepherosa Ziehau bus_dmamap_unload(dtag, dmap); 3856*2d586421SSepherosa Ziehau bus_dmamem_free(dtag, addr, dmap); 3857*2d586421SSepherosa Ziehau bus_dma_tag_destroy(dtag); 3858*2d586421SSepherosa Ziehau } 3859*2d586421SSepherosa Ziehau } 3860