1 1.65 thorpej /* $NetBSD: if_mec.c,v 1.65 2023/12/20 15:29:07 thorpej Exp $ */ 2 1.1 tsutsui 3 1.20 tsutsui /*- 4 1.31 tsutsui * Copyright (c) 2004, 2008 Izumi Tsutsui. All rights reserved. 5 1.1 tsutsui * 6 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 7 1.1 tsutsui * modification, are permitted provided that the following conditions 8 1.1 tsutsui * are met: 9 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 10 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 11 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 13 1.1 tsutsui * documentation and/or other materials provided with the distribution. 14 1.1 tsutsui * 15 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 tsutsui */ 26 1.1 tsutsui 27 1.1 tsutsui /* 28 1.1 tsutsui * Copyright (c) 2003 Christopher SEKIYA 29 1.1 tsutsui * All rights reserved. 30 1.1 tsutsui * 31 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 32 1.1 tsutsui * modification, are permitted provided that the following conditions 33 1.1 tsutsui * are met: 34 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 35 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 36 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 37 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 38 1.1 tsutsui * documentation and/or other materials provided with the distribution. 39 1.1 tsutsui * 3. All advertising materials mentioning features or use of this software 40 1.1 tsutsui * must display the following acknowledgement: 41 1.1 tsutsui * This product includes software developed for the 42 1.1 tsutsui * NetBSD Project. See http://www.NetBSD.org/ for 43 1.1 tsutsui * information about NetBSD. 44 1.1 tsutsui * 4. The name of the author may not be used to endorse or promote products 45 1.1 tsutsui * derived from this software without specific prior written permission. 46 1.1 tsutsui * 47 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 1.1 tsutsui */ 58 1.1 tsutsui 59 1.1 tsutsui /* 60 1.14 tsutsui * MACE MAC-110 Ethernet driver 61 1.1 tsutsui */ 62 1.1 tsutsui 63 1.1 tsutsui #include <sys/cdefs.h> 64 1.65 thorpej __KERNEL_RCSID(0, "$NetBSD: if_mec.c,v 1.65 2023/12/20 15:29:07 thorpej Exp $"); 65 1.1 tsutsui 66 1.1 tsutsui #include "opt_ddb.h" 67 1.1 tsutsui 68 1.1 tsutsui #include <sys/param.h> 69 1.1 tsutsui #include <sys/systm.h> 70 1.1 tsutsui #include <sys/device.h> 71 1.1 tsutsui #include <sys/callout.h> 72 1.1 tsutsui #include <sys/mbuf.h> 73 1.1 tsutsui #include <sys/kernel.h> 74 1.1 tsutsui #include <sys/socket.h> 75 1.1 tsutsui #include <sys/ioctl.h> 76 1.1 tsutsui #include <sys/errno.h> 77 1.1 tsutsui 78 1.51 riastrad #include <sys/rndsource.h> 79 1.1 tsutsui 80 1.1 tsutsui #include <net/if.h> 81 1.1 tsutsui #include <net/if_dl.h> 82 1.1 tsutsui #include <net/if_media.h> 83 1.1 tsutsui #include <net/if_ether.h> 84 1.1 tsutsui 85 1.34 tsutsui #include <netinet/in.h> 86 1.34 tsutsui #include <netinet/in_systm.h> 87 1.34 tsutsui #include <netinet/ip.h> 88 1.34 tsutsui #include <netinet/tcp.h> 89 1.34 tsutsui #include <netinet/udp.h> 90 1.34 tsutsui 91 1.1 tsutsui #include <net/bpf.h> 92 1.1 tsutsui 93 1.46 dyoung #include <sys/bus.h> 94 1.1 tsutsui #include <machine/intr.h> 95 1.1 tsutsui #include <machine/machtype.h> 96 1.1 tsutsui 97 1.1 tsutsui #include <dev/mii/mii.h> 98 1.1 tsutsui #include <dev/mii/miivar.h> 99 1.1 tsutsui 100 1.1 tsutsui #include <sgimips/mace/macevar.h> 101 1.1 tsutsui #include <sgimips/mace/if_mecreg.h> 102 1.1 tsutsui 103 1.1 tsutsui #include <dev/arcbios/arcbios.h> 104 1.1 tsutsui #include <dev/arcbios/arcbiosvar.h> 105 1.1 tsutsui 106 1.1 tsutsui /* #define MEC_DEBUG */ 107 1.1 tsutsui 108 1.1 tsutsui #ifdef MEC_DEBUG 109 1.1 tsutsui #define MEC_DEBUG_RESET 0x01 110 1.1 tsutsui #define MEC_DEBUG_START 0x02 111 1.1 tsutsui #define MEC_DEBUG_STOP 0x04 112 1.1 tsutsui #define MEC_DEBUG_INTR 0x08 113 1.1 tsutsui #define MEC_DEBUG_RXINTR 0x10 114 1.1 tsutsui #define MEC_DEBUG_TXINTR 0x20 115 1.31 tsutsui #define MEC_DEBUG_TXSEGS 0x40 116 1.1 tsutsui uint32_t mec_debug = 0; 117 1.1 tsutsui #define DPRINTF(x, y) if (mec_debug & (x)) printf y 118 1.1 tsutsui #else 119 1.1 tsutsui #define DPRINTF(x, y) /* nothing */ 120 1.1 tsutsui #endif 121 1.1 tsutsui 122 1.31 tsutsui /* #define MEC_EVENT_COUNTERS */ 123 1.31 tsutsui 124 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 125 1.31 tsutsui #define MEC_EVCNT_INCR(ev) (ev)->ev_count++ 126 1.31 tsutsui #else 127 1.31 tsutsui #define MEC_EVCNT_INCR(ev) do {} while (/* CONSTCOND */ 0) 128 1.31 tsutsui #endif 129 1.31 tsutsui 130 1.1 tsutsui /* 131 1.1 tsutsui * Transmit descriptor list size 132 1.1 tsutsui */ 133 1.1 tsutsui #define MEC_NTXDESC 64 134 1.1 tsutsui #define MEC_NTXDESC_MASK (MEC_NTXDESC - 1) 135 1.1 tsutsui #define MEC_NEXTTX(x) (((x) + 1) & MEC_NTXDESC_MASK) 136 1.21 tsutsui #define MEC_NTXDESC_RSVD 4 137 1.29 tsutsui #define MEC_NTXDESC_INTR 8 138 1.1 tsutsui 139 1.1 tsutsui /* 140 1.1 tsutsui * software state for TX 141 1.1 tsutsui */ 142 1.1 tsutsui struct mec_txsoft { 143 1.1 tsutsui struct mbuf *txs_mbuf; /* head of our mbuf chain */ 144 1.1 tsutsui bus_dmamap_t txs_dmamap; /* our DMA map */ 145 1.1 tsutsui uint32_t txs_flags; 146 1.1 tsutsui #define MEC_TXS_BUFLEN_MASK 0x0000007f /* data len in txd_buf */ 147 1.31 tsutsui #define MEC_TXS_TXDPTR 0x00000080 /* concat txd_ptr is used */ 148 1.1 tsutsui }; 149 1.1 tsutsui 150 1.1 tsutsui /* 151 1.1 tsutsui * Transmit buffer descriptor 152 1.1 tsutsui */ 153 1.1 tsutsui #define MEC_TXDESCSIZE 128 154 1.1 tsutsui #define MEC_NTXPTR 3 155 1.31 tsutsui #define MEC_TXD_BUFOFFSET sizeof(uint64_t) 156 1.31 tsutsui #define MEC_TXD_BUFOFFSET1 \ 157 1.31 tsutsui (sizeof(uint64_t) + sizeof(uint64_t) * MEC_NTXPTR) 158 1.1 tsutsui #define MEC_TXD_BUFSIZE (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET) 159 1.31 tsutsui #define MEC_TXD_BUFSIZE1 (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET1) 160 1.1 tsutsui #define MEC_TXD_BUFSTART(len) (MEC_TXD_BUFSIZE - (len)) 161 1.1 tsutsui #define MEC_TXD_ALIGN 8 162 1.31 tsutsui #define MEC_TXD_ALIGNMASK (MEC_TXD_ALIGN - 1) 163 1.1 tsutsui #define MEC_TXD_ROUNDUP(addr) \ 164 1.31 tsutsui (((addr) + MEC_TXD_ALIGNMASK) & ~(uint64_t)MEC_TXD_ALIGNMASK) 165 1.31 tsutsui #define MEC_NTXSEG 16 166 1.1 tsutsui 167 1.1 tsutsui struct mec_txdesc { 168 1.1 tsutsui volatile uint64_t txd_cmd; 169 1.1 tsutsui #define MEC_TXCMD_DATALEN 0x000000000000ffff /* data length */ 170 1.1 tsutsui #define MEC_TXCMD_BUFSTART 0x00000000007f0000 /* start byte offset */ 171 1.1 tsutsui #define TXCMD_BUFSTART(x) ((x) << 16) 172 1.1 tsutsui #define MEC_TXCMD_TERMDMA 0x0000000000800000 /* stop DMA on abort */ 173 1.1 tsutsui #define MEC_TXCMD_TXINT 0x0000000001000000 /* INT after TX done */ 174 1.1 tsutsui #define MEC_TXCMD_PTR1 0x0000000002000000 /* valid 1st txd_ptr */ 175 1.1 tsutsui #define MEC_TXCMD_PTR2 0x0000000004000000 /* valid 2nd txd_ptr */ 176 1.1 tsutsui #define MEC_TXCMD_PTR3 0x0000000008000000 /* valid 3rd txd_ptr */ 177 1.1 tsutsui #define MEC_TXCMD_UNUSED 0xfffffffff0000000ULL /* should be zero */ 178 1.1 tsutsui 179 1.1 tsutsui #define txd_stat txd_cmd 180 1.1 tsutsui #define MEC_TXSTAT_LEN 0x000000000000ffff /* TX length */ 181 1.1 tsutsui #define MEC_TXSTAT_COLCNT 0x00000000000f0000 /* collision count */ 182 1.1 tsutsui #define MEC_TXSTAT_COLCNT_SHIFT 16 183 1.1 tsutsui #define MEC_TXSTAT_LATE_COL 0x0000000000100000 /* late collision */ 184 1.1 tsutsui #define MEC_TXSTAT_CRCERROR 0x0000000000200000 /* */ 185 1.1 tsutsui #define MEC_TXSTAT_DEFERRED 0x0000000000400000 /* */ 186 1.1 tsutsui #define MEC_TXSTAT_SUCCESS 0x0000000000800000 /* TX complete */ 187 1.1 tsutsui #define MEC_TXSTAT_TOOBIG 0x0000000001000000 /* */ 188 1.1 tsutsui #define MEC_TXSTAT_UNDERRUN 0x0000000002000000 /* */ 189 1.1 tsutsui #define MEC_TXSTAT_COLLISIONS 0x0000000004000000 /* */ 190 1.1 tsutsui #define MEC_TXSTAT_EXDEFERRAL 0x0000000008000000 /* */ 191 1.1 tsutsui #define MEC_TXSTAT_COLLIDED 0x0000000010000000 /* */ 192 1.1 tsutsui #define MEC_TXSTAT_UNUSED 0x7fffffffe0000000ULL /* should be zero */ 193 1.1 tsutsui #define MEC_TXSTAT_SENT 0x8000000000000000ULL /* packet sent */ 194 1.1 tsutsui 195 1.31 tsutsui union { 196 1.31 tsutsui uint64_t txptr[MEC_NTXPTR]; 197 1.1 tsutsui #define MEC_TXPTR_UNUSED2 0x0000000000000007 /* should be zero */ 198 1.1 tsutsui #define MEC_TXPTR_DMAADDR 0x00000000fffffff8 /* TX DMA address */ 199 1.1 tsutsui #define MEC_TXPTR_LEN 0x0000ffff00000000ULL /* buffer length */ 200 1.1 tsutsui #define TXPTR_LEN(x) ((uint64_t)(x) << 32) 201 1.1 tsutsui #define MEC_TXPTR_UNUSED1 0xffff000000000000ULL /* should be zero */ 202 1.1 tsutsui 203 1.31 tsutsui uint8_t txbuf[MEC_TXD_BUFSIZE]; 204 1.31 tsutsui } txd_data; 205 1.31 tsutsui #define txd_ptr txd_data.txptr 206 1.31 tsutsui #define txd_buf txd_data.txbuf 207 1.1 tsutsui }; 208 1.1 tsutsui 209 1.1 tsutsui /* 210 1.1 tsutsui * Receive buffer size 211 1.1 tsutsui */ 212 1.1 tsutsui #define MEC_NRXDESC 16 213 1.1 tsutsui #define MEC_NRXDESC_MASK (MEC_NRXDESC - 1) 214 1.1 tsutsui #define MEC_NEXTRX(x) (((x) + 1) & MEC_NRXDESC_MASK) 215 1.1 tsutsui 216 1.1 tsutsui /* 217 1.1 tsutsui * Receive buffer description 218 1.1 tsutsui */ 219 1.1 tsutsui #define MEC_RXDESCSIZE 4096 /* umm, should be 4kbyte aligned */ 220 1.1 tsutsui #define MEC_RXD_NRXPAD 3 221 1.1 tsutsui #define MEC_RXD_DMAOFFSET (1 + MEC_RXD_NRXPAD) 222 1.1 tsutsui #define MEC_RXD_BUFOFFSET (MEC_RXD_DMAOFFSET * sizeof(uint64_t)) 223 1.1 tsutsui #define MEC_RXD_BUFSIZE (MEC_RXDESCSIZE - MEC_RXD_BUFOFFSET) 224 1.1 tsutsui 225 1.1 tsutsui struct mec_rxdesc { 226 1.1 tsutsui volatile uint64_t rxd_stat; 227 1.1 tsutsui #define MEC_RXSTAT_LEN 0x000000000000ffff /* data length */ 228 1.1 tsutsui #define MEC_RXSTAT_VIOLATION 0x0000000000010000 /* code violation (?) */ 229 1.1 tsutsui #define MEC_RXSTAT_UNUSED2 0x0000000000020000 /* unknown (?) */ 230 1.1 tsutsui #define MEC_RXSTAT_CRCERROR 0x0000000000040000 /* CRC error */ 231 1.1 tsutsui #define MEC_RXSTAT_MULTICAST 0x0000000000080000 /* multicast packet */ 232 1.1 tsutsui #define MEC_RXSTAT_BROADCAST 0x0000000000100000 /* broadcast packet */ 233 1.1 tsutsui #define MEC_RXSTAT_INVALID 0x0000000000200000 /* invalid preamble */ 234 1.1 tsutsui #define MEC_RXSTAT_LONGEVENT 0x0000000000400000 /* long packet */ 235 1.1 tsutsui #define MEC_RXSTAT_BADPACKET 0x0000000000800000 /* bad packet */ 236 1.1 tsutsui #define MEC_RXSTAT_CAREVENT 0x0000000001000000 /* carrier event */ 237 1.1 tsutsui #define MEC_RXSTAT_MATCHMCAST 0x0000000002000000 /* match multicast */ 238 1.1 tsutsui #define MEC_RXSTAT_MATCHMAC 0x0000000004000000 /* match MAC */ 239 1.1 tsutsui #define MEC_RXSTAT_SEQNUM 0x00000000f8000000 /* sequence number */ 240 1.1 tsutsui #define MEC_RXSTAT_CKSUM 0x0000ffff00000000ULL /* IP checksum */ 241 1.34 tsutsui #define RXSTAT_CKSUM(x) (((uint64_t)(x) & MEC_RXSTAT_CKSUM) >> 32) 242 1.1 tsutsui #define MEC_RXSTAT_UNUSED1 0x7fff000000000000ULL /* should be zero */ 243 1.1 tsutsui #define MEC_RXSTAT_RECEIVED 0x8000000000000000ULL /* set to 1 on RX */ 244 1.1 tsutsui uint64_t rxd_pad1[MEC_RXD_NRXPAD]; 245 1.1 tsutsui uint8_t rxd_buf[MEC_RXD_BUFSIZE]; 246 1.1 tsutsui }; 247 1.1 tsutsui 248 1.1 tsutsui /* 249 1.1 tsutsui * control structures for DMA ops 250 1.1 tsutsui */ 251 1.1 tsutsui struct mec_control_data { 252 1.1 tsutsui /* 253 1.1 tsutsui * TX descriptors and buffers 254 1.1 tsutsui */ 255 1.1 tsutsui struct mec_txdesc mcd_txdesc[MEC_NTXDESC]; 256 1.1 tsutsui 257 1.1 tsutsui /* 258 1.1 tsutsui * RX descriptors and buffers 259 1.1 tsutsui */ 260 1.1 tsutsui struct mec_rxdesc mcd_rxdesc[MEC_NRXDESC]; 261 1.1 tsutsui }; 262 1.1 tsutsui 263 1.1 tsutsui /* 264 1.1 tsutsui * It _seems_ there are some restrictions on descriptor address: 265 1.1 tsutsui * 266 1.1 tsutsui * - Base address of txdescs should be 8kbyte aligned 267 1.1 tsutsui * - Each txdesc should be 128byte aligned 268 1.1 tsutsui * - Each rxdesc should be 4kbyte aligned 269 1.1 tsutsui * 270 1.3 tsutsui * So we should specify 8k align to allocalte txdescs. 271 1.1 tsutsui * In this case, sizeof(struct mec_txdesc) * MEC_NTXDESC is 8192 272 1.1 tsutsui * so rxdescs are also allocated at 4kbyte aligned. 273 1.1 tsutsui */ 274 1.1 tsutsui #define MEC_CONTROL_DATA_ALIGN (8 * 1024) 275 1.1 tsutsui 276 1.1 tsutsui #define MEC_CDOFF(x) offsetof(struct mec_control_data, x) 277 1.1 tsutsui #define MEC_CDTXOFF(x) MEC_CDOFF(mcd_txdesc[(x)]) 278 1.1 tsutsui #define MEC_CDRXOFF(x) MEC_CDOFF(mcd_rxdesc[(x)]) 279 1.1 tsutsui 280 1.1 tsutsui /* 281 1.1 tsutsui * software state per device 282 1.1 tsutsui */ 283 1.1 tsutsui struct mec_softc { 284 1.19 tsutsui device_t sc_dev; /* generic device structures */ 285 1.1 tsutsui 286 1.1 tsutsui bus_space_tag_t sc_st; /* bus_space tag */ 287 1.1 tsutsui bus_space_handle_t sc_sh; /* bus_space handle */ 288 1.1 tsutsui bus_dma_tag_t sc_dmat; /* bus_dma tag */ 289 1.1 tsutsui 290 1.1 tsutsui struct ethercom sc_ethercom; /* Ethernet common part */ 291 1.1 tsutsui 292 1.1 tsutsui struct mii_data sc_mii; /* MII/media information */ 293 1.1 tsutsui int sc_phyaddr; /* MII address */ 294 1.1 tsutsui struct callout sc_tick_ch; /* tick callout */ 295 1.1 tsutsui 296 1.1 tsutsui uint8_t sc_enaddr[ETHER_ADDR_LEN]; /* MAC address */ 297 1.1 tsutsui 298 1.1 tsutsui bus_dmamap_t sc_cddmamap; /* bus_dma map for control data */ 299 1.1 tsutsui #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr 300 1.1 tsutsui 301 1.14 tsutsui /* pointer to allocated control data */ 302 1.1 tsutsui struct mec_control_data *sc_control_data; 303 1.1 tsutsui #define sc_txdesc sc_control_data->mcd_txdesc 304 1.1 tsutsui #define sc_rxdesc sc_control_data->mcd_rxdesc 305 1.1 tsutsui 306 1.1 tsutsui /* software state for TX descs */ 307 1.1 tsutsui struct mec_txsoft sc_txsoft[MEC_NTXDESC]; 308 1.1 tsutsui 309 1.1 tsutsui int sc_txpending; /* number of TX requests pending */ 310 1.1 tsutsui int sc_txdirty; /* first dirty TX descriptor */ 311 1.1 tsutsui int sc_txlast; /* last used TX descriptor */ 312 1.1 tsutsui 313 1.1 tsutsui int sc_rxptr; /* next ready RX buffer */ 314 1.1 tsutsui 315 1.47 tls krndsource_t sc_rnd_source; /* random source */ 316 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 317 1.31 tsutsui struct evcnt sc_ev_txpkts; /* TX packets queued total */ 318 1.31 tsutsui struct evcnt sc_ev_txdpad; /* TX packets padded in txdesc buf */ 319 1.31 tsutsui struct evcnt sc_ev_txdbuf; /* TX packets copied to txdesc buf */ 320 1.31 tsutsui struct evcnt sc_ev_txptr1; /* TX packets using concat ptr1 */ 321 1.31 tsutsui struct evcnt sc_ev_txptr1a; /* TX packets w/ptr1 ~160bytes */ 322 1.31 tsutsui struct evcnt sc_ev_txptr1b; /* TX packets w/ptr1 ~256bytes */ 323 1.31 tsutsui struct evcnt sc_ev_txptr1c; /* TX packets w/ptr1 ~512bytes */ 324 1.31 tsutsui struct evcnt sc_ev_txptr1d; /* TX packets w/ptr1 ~1024bytes */ 325 1.31 tsutsui struct evcnt sc_ev_txptr1e; /* TX packets w/ptr1 >1024bytes */ 326 1.31 tsutsui struct evcnt sc_ev_txptr2; /* TX packets using concat ptr1,2 */ 327 1.31 tsutsui struct evcnt sc_ev_txptr2a; /* TX packets w/ptr2 ~160bytes */ 328 1.31 tsutsui struct evcnt sc_ev_txptr2b; /* TX packets w/ptr2 ~256bytes */ 329 1.31 tsutsui struct evcnt sc_ev_txptr2c; /* TX packets w/ptr2 ~512bytes */ 330 1.31 tsutsui struct evcnt sc_ev_txptr2d; /* TX packets w/ptr2 ~1024bytes */ 331 1.31 tsutsui struct evcnt sc_ev_txptr2e; /* TX packets w/ptr2 >1024bytes */ 332 1.31 tsutsui struct evcnt sc_ev_txptr3; /* TX packets using concat ptr1,2,3 */ 333 1.31 tsutsui struct evcnt sc_ev_txptr3a; /* TX packets w/ptr3 ~160bytes */ 334 1.31 tsutsui struct evcnt sc_ev_txptr3b; /* TX packets w/ptr3 ~256bytes */ 335 1.31 tsutsui struct evcnt sc_ev_txptr3c; /* TX packets w/ptr3 ~512bytes */ 336 1.31 tsutsui struct evcnt sc_ev_txptr3d; /* TX packets w/ptr3 ~1024bytes */ 337 1.31 tsutsui struct evcnt sc_ev_txptr3e; /* TX packets w/ptr3 >1024bytes */ 338 1.31 tsutsui struct evcnt sc_ev_txmbuf; /* TX packets copied to new mbufs */ 339 1.31 tsutsui struct evcnt sc_ev_txmbufa; /* TX packets w/mbuf ~160bytes */ 340 1.31 tsutsui struct evcnt sc_ev_txmbufb; /* TX packets w/mbuf ~256bytes */ 341 1.31 tsutsui struct evcnt sc_ev_txmbufc; /* TX packets w/mbuf ~512bytes */ 342 1.31 tsutsui struct evcnt sc_ev_txmbufd; /* TX packets w/mbuf ~1024bytes */ 343 1.31 tsutsui struct evcnt sc_ev_txmbufe; /* TX packets w/mbuf >1024bytes */ 344 1.31 tsutsui struct evcnt sc_ev_txptrs; /* TX packets using ptrs total */ 345 1.31 tsutsui struct evcnt sc_ev_txptrc0; /* TX packets w/ptrs no hdr chain */ 346 1.31 tsutsui struct evcnt sc_ev_txptrc1; /* TX packets w/ptrs 1 hdr chain */ 347 1.31 tsutsui struct evcnt sc_ev_txptrc2; /* TX packets w/ptrs 2 hdr chains */ 348 1.31 tsutsui struct evcnt sc_ev_txptrc3; /* TX packets w/ptrs 3 hdr chains */ 349 1.31 tsutsui struct evcnt sc_ev_txptrc4; /* TX packets w/ptrs 4 hdr chains */ 350 1.31 tsutsui struct evcnt sc_ev_txptrc5; /* TX packets w/ptrs 5 hdr chains */ 351 1.31 tsutsui struct evcnt sc_ev_txptrc6; /* TX packets w/ptrs >5 hdr chains */ 352 1.31 tsutsui struct evcnt sc_ev_txptrh0; /* TX packets w/ptrs ~8bytes hdr */ 353 1.31 tsutsui struct evcnt sc_ev_txptrh1; /* TX packets w/ptrs ~16bytes hdr */ 354 1.31 tsutsui struct evcnt sc_ev_txptrh2; /* TX packets w/ptrs ~32bytes hdr */ 355 1.31 tsutsui struct evcnt sc_ev_txptrh3; /* TX packets w/ptrs ~64bytes hdr */ 356 1.31 tsutsui struct evcnt sc_ev_txptrh4; /* TX packets w/ptrs ~80bytes hdr */ 357 1.31 tsutsui struct evcnt sc_ev_txptrh5; /* TX packets w/ptrs ~96bytes hdr */ 358 1.31 tsutsui struct evcnt sc_ev_txdstall; /* TX stalled due to no txdesc */ 359 1.31 tsutsui struct evcnt sc_ev_txempty; /* TX empty interrupts */ 360 1.31 tsutsui struct evcnt sc_ev_txsent; /* TX sent interrupts */ 361 1.31 tsutsui #endif 362 1.1 tsutsui }; 363 1.1 tsutsui 364 1.1 tsutsui #define MEC_CDTXADDR(sc, x) ((sc)->sc_cddma + MEC_CDTXOFF(x)) 365 1.1 tsutsui #define MEC_CDRXADDR(sc, x) ((sc)->sc_cddma + MEC_CDRXOFF(x)) 366 1.1 tsutsui 367 1.1 tsutsui #define MEC_TXDESCSYNC(sc, x, ops) \ 368 1.1 tsutsui bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 369 1.1 tsutsui MEC_CDTXOFF(x), MEC_TXDESCSIZE, (ops)) 370 1.1 tsutsui #define MEC_TXCMDSYNC(sc, x, ops) \ 371 1.1 tsutsui bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 372 1.1 tsutsui MEC_CDTXOFF(x), sizeof(uint64_t), (ops)) 373 1.1 tsutsui 374 1.1 tsutsui #define MEC_RXSTATSYNC(sc, x, ops) \ 375 1.1 tsutsui bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 376 1.1 tsutsui MEC_CDRXOFF(x), sizeof(uint64_t), (ops)) 377 1.1 tsutsui #define MEC_RXBUFSYNC(sc, x, len, ops) \ 378 1.1 tsutsui bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 379 1.1 tsutsui MEC_CDRXOFF(x) + MEC_RXD_BUFOFFSET, \ 380 1.1 tsutsui MEC_ETHER_ALIGN + (len), (ops)) 381 1.1 tsutsui 382 1.1 tsutsui /* XXX these values should be moved to <net/if_ether.h> ? */ 383 1.1 tsutsui #define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) 384 1.1 tsutsui #define MEC_ETHER_ALIGN 2 385 1.1 tsutsui 386 1.19 tsutsui static int mec_match(device_t, cfdata_t, void *); 387 1.19 tsutsui static void mec_attach(device_t, device_t, void *); 388 1.1 tsutsui 389 1.58 msaitoh static int mec_mii_readreg(device_t, int, int, uint16_t *); 390 1.58 msaitoh static int mec_mii_writereg(device_t, int, int, uint16_t); 391 1.19 tsutsui static int mec_mii_wait(struct mec_softc *); 392 1.49 matt static void mec_statchg(struct ifnet *); 393 1.1 tsutsui 394 1.19 tsutsui static int mec_init(struct ifnet * ifp); 395 1.19 tsutsui static void mec_start(struct ifnet *); 396 1.19 tsutsui static void mec_watchdog(struct ifnet *); 397 1.19 tsutsui static void mec_tick(void *); 398 1.19 tsutsui static int mec_ioctl(struct ifnet *, u_long, void *); 399 1.19 tsutsui static void mec_reset(struct mec_softc *); 400 1.19 tsutsui static void mec_setfilter(struct mec_softc *); 401 1.19 tsutsui static int mec_intr(void *arg); 402 1.19 tsutsui static void mec_stop(struct ifnet *, int); 403 1.19 tsutsui static void mec_rxintr(struct mec_softc *); 404 1.34 tsutsui static void mec_rxcsum(struct mec_softc *, struct mbuf *, uint16_t, 405 1.34 tsutsui uint32_t); 406 1.21 tsutsui static void mec_txintr(struct mec_softc *, uint32_t); 407 1.36 tsutsui static bool mec_shutdown(device_t, int); 408 1.1 tsutsui 409 1.19 tsutsui CFATTACH_DECL_NEW(mec, sizeof(struct mec_softc), 410 1.1 tsutsui mec_match, mec_attach, NULL, NULL); 411 1.1 tsutsui 412 1.1 tsutsui static int mec_matched = 0; 413 1.1 tsutsui 414 1.19 tsutsui static int 415 1.19 tsutsui mec_match(device_t parent, cfdata_t cf, void *aux) 416 1.1 tsutsui { 417 1.1 tsutsui 418 1.1 tsutsui /* allow only one device */ 419 1.1 tsutsui if (mec_matched) 420 1.1 tsutsui return 0; 421 1.1 tsutsui 422 1.1 tsutsui mec_matched = 1; 423 1.1 tsutsui return 1; 424 1.1 tsutsui } 425 1.1 tsutsui 426 1.19 tsutsui static void 427 1.19 tsutsui mec_attach(device_t parent, device_t self, void *aux) 428 1.1 tsutsui { 429 1.19 tsutsui struct mec_softc *sc = device_private(self); 430 1.1 tsutsui struct mace_attach_args *maa = aux; 431 1.1 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 432 1.61 msaitoh struct mii_data *mii = &sc->sc_mii; 433 1.17 tsutsui uint64_t address, command; 434 1.6 martin const char *macaddr; 435 1.1 tsutsui struct mii_softc *child; 436 1.1 tsutsui bus_dma_segment_t seg; 437 1.1 tsutsui int i, err, rseg; 438 1.18 martin bool mac_is_fake; 439 1.1 tsutsui 440 1.19 tsutsui sc->sc_dev = self; 441 1.1 tsutsui sc->sc_st = maa->maa_st; 442 1.1 tsutsui if (bus_space_subregion(sc->sc_st, maa->maa_sh, 443 1.1 tsutsui maa->maa_offset, 0, &sc->sc_sh) != 0) { 444 1.19 tsutsui aprint_error(": can't map i/o space\n"); 445 1.1 tsutsui return; 446 1.1 tsutsui } 447 1.1 tsutsui 448 1.1 tsutsui /* set up DMA structures */ 449 1.1 tsutsui sc->sc_dmat = maa->maa_dmat; 450 1.1 tsutsui 451 1.1 tsutsui /* 452 1.1 tsutsui * Allocate the control data structures, and create and load the 453 1.1 tsutsui * DMA map for it. 454 1.1 tsutsui */ 455 1.1 tsutsui if ((err = bus_dmamem_alloc(sc->sc_dmat, 456 1.1 tsutsui sizeof(struct mec_control_data), MEC_CONTROL_DATA_ALIGN, 0, 457 1.1 tsutsui &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 458 1.19 tsutsui aprint_error(": unable to allocate control data, error = %d\n", 459 1.19 tsutsui err); 460 1.1 tsutsui goto fail_0; 461 1.1 tsutsui } 462 1.1 tsutsui /* 463 1.1 tsutsui * XXX needs re-think... 464 1.1 tsutsui * control data structures contain whole RX data buffer, so 465 1.1 tsutsui * BUS_DMA_COHERENT (which disables cache) may cause some performance 466 1.1 tsutsui * issue on copying data from the RX buffer to mbuf on normal memory, 467 1.1 tsutsui * though we have to make sure all bus_dmamap_sync(9) ops are called 468 1.14 tsutsui * properly in that case. 469 1.1 tsutsui */ 470 1.1 tsutsui if ((err = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 471 1.1 tsutsui sizeof(struct mec_control_data), 472 1.10 christos (void **)&sc->sc_control_data, /*BUS_DMA_COHERENT*/ 0)) != 0) { 473 1.19 tsutsui aprint_error(": unable to map control data, error = %d\n", err); 474 1.1 tsutsui goto fail_1; 475 1.1 tsutsui } 476 1.1 tsutsui memset(sc->sc_control_data, 0, sizeof(struct mec_control_data)); 477 1.1 tsutsui 478 1.1 tsutsui if ((err = bus_dmamap_create(sc->sc_dmat, 479 1.1 tsutsui sizeof(struct mec_control_data), 1, 480 1.1 tsutsui sizeof(struct mec_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { 481 1.19 tsutsui aprint_error(": unable to create control data DMA map," 482 1.19 tsutsui " error = %d\n", err); 483 1.1 tsutsui goto fail_2; 484 1.1 tsutsui } 485 1.1 tsutsui if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, 486 1.1 tsutsui sc->sc_control_data, sizeof(struct mec_control_data), NULL, 487 1.1 tsutsui BUS_DMA_NOWAIT)) != 0) { 488 1.19 tsutsui aprint_error(": unable to load control data DMA map," 489 1.19 tsutsui " error = %d\n", err); 490 1.1 tsutsui goto fail_3; 491 1.1 tsutsui } 492 1.1 tsutsui 493 1.1 tsutsui /* create TX buffer DMA maps */ 494 1.1 tsutsui for (i = 0; i < MEC_NTXDESC; i++) { 495 1.1 tsutsui if ((err = bus_dmamap_create(sc->sc_dmat, 496 1.31 tsutsui MCLBYTES, MEC_NTXSEG, MCLBYTES, PAGE_SIZE, 0, 497 1.1 tsutsui &sc->sc_txsoft[i].txs_dmamap)) != 0) { 498 1.19 tsutsui aprint_error(": unable to create tx DMA map %d," 499 1.19 tsutsui " error = %d\n", i, err); 500 1.1 tsutsui goto fail_4; 501 1.1 tsutsui } 502 1.1 tsutsui } 503 1.1 tsutsui 504 1.11 ad callout_init(&sc->sc_tick_ch, 0); 505 1.1 tsutsui 506 1.14 tsutsui /* get Ethernet address from ARCBIOS */ 507 1.45 matt if ((macaddr = arcbios_GetEnvironmentVariable("eaddr")) == NULL) { 508 1.19 tsutsui aprint_error(": unable to get MAC address!\n"); 509 1.1 tsutsui goto fail_4; 510 1.1 tsutsui } 511 1.18 martin /* 512 1.18 martin * On some machines the DS2502 chip storing the serial number/ 513 1.18 martin * mac address is on the pci riser board - if this board is 514 1.18 martin * missing, ARCBIOS will not know a good ethernet address (but 515 1.18 martin * otherwise the machine will work fine). 516 1.18 martin */ 517 1.18 martin mac_is_fake = false; 518 1.18 martin if (strcmp(macaddr, "ff:ff:ff:ff:ff:ff") == 0) { 519 1.18 martin uint32_t ui = 0; 520 1.18 martin const char * netaddr = 521 1.45 matt arcbios_GetEnvironmentVariable("netaddr"); 522 1.18 martin 523 1.18 martin /* 524 1.18 martin * Create a MAC address by abusing the "netaddr" env var 525 1.18 martin */ 526 1.18 martin sc->sc_enaddr[0] = 0xf2; 527 1.18 martin sc->sc_enaddr[1] = 0x0b; 528 1.18 martin sc->sc_enaddr[2] = 0xa4; 529 1.18 martin if (netaddr) { 530 1.18 martin mac_is_fake = true; 531 1.18 martin while (*netaddr) { 532 1.18 martin int v = 0; 533 1.18 martin while (*netaddr && *netaddr != '.') { 534 1.18 martin if (*netaddr >= '0' && *netaddr <= '9') 535 1.18 martin v = v*10 + (*netaddr - '0'); 536 1.18 martin netaddr++; 537 1.18 martin } 538 1.18 martin ui <<= 8; 539 1.18 martin ui |= v; 540 1.18 martin if (*netaddr == '.') 541 1.18 martin netaddr++; 542 1.18 martin } 543 1.18 martin } 544 1.18 martin memcpy(sc->sc_enaddr+3, ((uint8_t *)&ui)+1, 3); 545 1.18 martin } 546 1.18 martin if (!mac_is_fake) 547 1.44 tsutsui ether_aton_r(sc->sc_enaddr, sizeof(sc->sc_enaddr), macaddr); 548 1.1 tsutsui 549 1.17 tsutsui /* set the Ethernet address */ 550 1.17 tsutsui address = 0; 551 1.17 tsutsui for (i = 0; i < ETHER_ADDR_LEN; i++) { 552 1.17 tsutsui address = address << 8; 553 1.17 tsutsui address |= sc->sc_enaddr[i]; 554 1.17 tsutsui } 555 1.17 tsutsui bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_STATION, address); 556 1.17 tsutsui 557 1.1 tsutsui /* reset device */ 558 1.1 tsutsui mec_reset(sc); 559 1.1 tsutsui 560 1.1 tsutsui command = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_MAC_CONTROL); 561 1.1 tsutsui 562 1.19 tsutsui aprint_normal(": MAC-110 Ethernet, rev %u\n", 563 1.17 tsutsui (u_int)((command & MEC_MAC_REVISION) >> MEC_MAC_REVISION_SHIFT)); 564 1.1 tsutsui 565 1.18 martin if (mac_is_fake) 566 1.19 tsutsui aprint_normal_dev(self, 567 1.19 tsutsui "could not get ethernet address from firmware" 568 1.18 martin " - generated one from the \"netaddr\" environment" 569 1.19 tsutsui " variable\n"); 570 1.19 tsutsui aprint_normal_dev(self, "Ethernet address %s\n", 571 1.1 tsutsui ether_sprintf(sc->sc_enaddr)); 572 1.1 tsutsui 573 1.1 tsutsui /* Done, now attach everything */ 574 1.1 tsutsui 575 1.61 msaitoh mii->mii_ifp = ifp; 576 1.61 msaitoh mii->mii_readreg = mec_mii_readreg; 577 1.61 msaitoh mii->mii_writereg = mec_mii_writereg; 578 1.61 msaitoh mii->mii_statchg = mec_statchg; 579 1.1 tsutsui 580 1.1 tsutsui /* Set up PHY properties */ 581 1.61 msaitoh sc->sc_ethercom.ec_mii = mii; 582 1.61 msaitoh ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 583 1.61 msaitoh mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 584 1.1 tsutsui 585 1.61 msaitoh child = LIST_FIRST(&mii->mii_phys); 586 1.1 tsutsui if (child == NULL) { 587 1.1 tsutsui /* No PHY attached */ 588 1.61 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 589 1.1 tsutsui 0, NULL); 590 1.61 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL); 591 1.1 tsutsui } else { 592 1.61 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 593 1.1 tsutsui sc->sc_phyaddr = child->mii_phy; 594 1.1 tsutsui } 595 1.1 tsutsui 596 1.19 tsutsui strcpy(ifp->if_xname, device_xname(self)); 597 1.1 tsutsui ifp->if_softc = sc; 598 1.1 tsutsui ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 599 1.1 tsutsui ifp->if_ioctl = mec_ioctl; 600 1.1 tsutsui ifp->if_start = mec_start; 601 1.1 tsutsui ifp->if_watchdog = mec_watchdog; 602 1.1 tsutsui ifp->if_init = mec_init; 603 1.1 tsutsui ifp->if_stop = mec_stop; 604 1.1 tsutsui ifp->if_mtu = ETHERMTU; 605 1.1 tsutsui IFQ_SET_READY(&ifp->if_snd); 606 1.1 tsutsui 607 1.34 tsutsui /* mec has dumb RX cksum support */ 608 1.34 tsutsui ifp->if_capabilities = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx; 609 1.34 tsutsui 610 1.32 tsutsui /* We can support 802.1Q VLAN-sized frames. */ 611 1.32 tsutsui sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 612 1.32 tsutsui 613 1.32 tsutsui /* attach the interface */ 614 1.1 tsutsui if_attach(ifp); 615 1.54 ozaki if_deferred_start_init(ifp, NULL); 616 1.1 tsutsui ether_ifattach(ifp, sc->sc_enaddr); 617 1.1 tsutsui 618 1.1 tsutsui /* establish interrupt */ 619 1.1 tsutsui cpu_intr_establish(maa->maa_intr, maa->maa_intrmask, mec_intr, sc); 620 1.1 tsutsui 621 1.19 tsutsui rnd_attach_source(&sc->sc_rnd_source, device_xname(self), 622 1.50 tls RND_TYPE_NET, RND_FLAG_DEFAULT); 623 1.1 tsutsui 624 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 625 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txpkts , EVCNT_TYPE_MISC, 626 1.31 tsutsui NULL, device_xname(self), "TX pkts queued total"); 627 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txdpad , EVCNT_TYPE_MISC, 628 1.31 tsutsui NULL, device_xname(self), "TX pkts padded in txdesc buf"); 629 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txdbuf , EVCNT_TYPE_MISC, 630 1.31 tsutsui NULL, device_xname(self), "TX pkts copied to txdesc buf"); 631 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1 , EVCNT_TYPE_MISC, 632 1.31 tsutsui NULL, device_xname(self), "TX pkts using concat ptr1"); 633 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1a , EVCNT_TYPE_MISC, 634 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr1 ~160bytes"); 635 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1b , EVCNT_TYPE_MISC, 636 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr1 ~256bytes"); 637 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1c , EVCNT_TYPE_MISC, 638 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr1 ~512bytes"); 639 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1d , EVCNT_TYPE_MISC, 640 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr1 ~1024bytes"); 641 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr1e , EVCNT_TYPE_MISC, 642 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr1 >1024bytes"); 643 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2 , EVCNT_TYPE_MISC, 644 1.31 tsutsui NULL, device_xname(self), "TX pkts using concat ptr1,2"); 645 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2a , EVCNT_TYPE_MISC, 646 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr2 ~160bytes"); 647 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2b , EVCNT_TYPE_MISC, 648 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr2 ~256bytes"); 649 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2c , EVCNT_TYPE_MISC, 650 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr2 ~512bytes"); 651 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2d , EVCNT_TYPE_MISC, 652 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr2 ~1024bytes"); 653 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr2e , EVCNT_TYPE_MISC, 654 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr2 >1024bytes"); 655 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3 , EVCNT_TYPE_MISC, 656 1.31 tsutsui NULL, device_xname(self), "TX pkts using concat ptr1,2,3"); 657 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3a , EVCNT_TYPE_MISC, 658 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr3 ~160bytes"); 659 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3b , EVCNT_TYPE_MISC, 660 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr3 ~256bytes"); 661 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3c , EVCNT_TYPE_MISC, 662 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr3 ~512bytes"); 663 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3d , EVCNT_TYPE_MISC, 664 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr3 ~1024bytes"); 665 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptr3e , EVCNT_TYPE_MISC, 666 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptr3 >1024bytes"); 667 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbuf , EVCNT_TYPE_MISC, 668 1.31 tsutsui NULL, device_xname(self), "TX pkts copied to new mbufs"); 669 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbufa , EVCNT_TYPE_MISC, 670 1.31 tsutsui NULL, device_xname(self), "TX pkts w/mbuf ~160bytes"); 671 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbufb , EVCNT_TYPE_MISC, 672 1.31 tsutsui NULL, device_xname(self), "TX pkts w/mbuf ~256bytes"); 673 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbufc , EVCNT_TYPE_MISC, 674 1.31 tsutsui NULL, device_xname(self), "TX pkts w/mbuf ~512bytes"); 675 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbufd , EVCNT_TYPE_MISC, 676 1.31 tsutsui NULL, device_xname(self), "TX pkts w/mbuf ~1024bytes"); 677 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txmbufe , EVCNT_TYPE_MISC, 678 1.31 tsutsui NULL, device_xname(self), "TX pkts w/mbuf >1024bytes"); 679 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrs , EVCNT_TYPE_MISC, 680 1.31 tsutsui NULL, device_xname(self), "TX pkts using ptrs total"); 681 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc0 , EVCNT_TYPE_MISC, 682 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs no hdr chain"); 683 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc1 , EVCNT_TYPE_MISC, 684 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs 1 hdr chain"); 685 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc2 , EVCNT_TYPE_MISC, 686 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs 2 hdr chains"); 687 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc3 , EVCNT_TYPE_MISC, 688 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs 3 hdr chains"); 689 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc4 , EVCNT_TYPE_MISC, 690 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs 4 hdr chains"); 691 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc5 , EVCNT_TYPE_MISC, 692 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs 5 hdr chains"); 693 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrc6 , EVCNT_TYPE_MISC, 694 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs >5 hdr chains"); 695 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh0 , EVCNT_TYPE_MISC, 696 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~8bytes hdr"); 697 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh1 , EVCNT_TYPE_MISC, 698 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~16bytes hdr"); 699 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh2 , EVCNT_TYPE_MISC, 700 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~32bytes hdr"); 701 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh3 , EVCNT_TYPE_MISC, 702 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~64bytes hdr"); 703 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh4 , EVCNT_TYPE_MISC, 704 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~80bytes hdr"); 705 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txptrh5 , EVCNT_TYPE_MISC, 706 1.31 tsutsui NULL, device_xname(self), "TX pkts w/ptrs ~96bytes hdr"); 707 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txdstall , EVCNT_TYPE_MISC, 708 1.31 tsutsui NULL, device_xname(self), "TX stalled due to no txdesc"); 709 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txempty , EVCNT_TYPE_MISC, 710 1.31 tsutsui NULL, device_xname(self), "TX empty interrupts"); 711 1.31 tsutsui evcnt_attach_dynamic(&sc->sc_ev_txsent , EVCNT_TYPE_MISC, 712 1.31 tsutsui NULL, device_xname(self), "TX sent interrupts"); 713 1.31 tsutsui #endif 714 1.31 tsutsui 715 1.1 tsutsui /* set shutdown hook to reset interface on powerdown */ 716 1.38 tsutsui if (pmf_device_register1(self, NULL, NULL, mec_shutdown)) 717 1.39 tsutsui pmf_class_network_register(self, ifp); 718 1.38 tsutsui else 719 1.37 tsutsui aprint_error_dev(self, "couldn't establish power handler\n"); 720 1.1 tsutsui 721 1.1 tsutsui return; 722 1.1 tsutsui 723 1.1 tsutsui /* 724 1.1 tsutsui * Free any resources we've allocated during the failed attach 725 1.1 tsutsui * attempt. Do this in reverse order and fall though. 726 1.1 tsutsui */ 727 1.1 tsutsui fail_4: 728 1.1 tsutsui for (i = 0; i < MEC_NTXDESC; i++) { 729 1.1 tsutsui if (sc->sc_txsoft[i].txs_dmamap != NULL) 730 1.1 tsutsui bus_dmamap_destroy(sc->sc_dmat, 731 1.1 tsutsui sc->sc_txsoft[i].txs_dmamap); 732 1.1 tsutsui } 733 1.1 tsutsui bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); 734 1.1 tsutsui fail_3: 735 1.1 tsutsui bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); 736 1.1 tsutsui fail_2: 737 1.10 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, 738 1.1 tsutsui sizeof(struct mec_control_data)); 739 1.1 tsutsui fail_1: 740 1.1 tsutsui bus_dmamem_free(sc->sc_dmat, &seg, rseg); 741 1.1 tsutsui fail_0: 742 1.1 tsutsui return; 743 1.1 tsutsui } 744 1.1 tsutsui 745 1.19 tsutsui static int 746 1.58 msaitoh mec_mii_readreg(device_t self, int phy, int reg, uint16_t *val) 747 1.1 tsutsui { 748 1.19 tsutsui struct mec_softc *sc = device_private(self); 749 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 750 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 751 1.58 msaitoh uint64_t data; 752 1.58 msaitoh int i, rv; 753 1.1 tsutsui 754 1.58 msaitoh if ((rv = mec_mii_wait(sc)) != 0) 755 1.58 msaitoh return rv; 756 1.1 tsutsui 757 1.7 tsutsui bus_space_write_8(st, sh, MEC_PHY_ADDRESS, 758 1.1 tsutsui (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); 759 1.12 macallan delay(25); 760 1.1 tsutsui bus_space_write_8(st, sh, MEC_PHY_READ_INITIATE, 1); 761 1.1 tsutsui delay(25); 762 1.12 macallan mec_mii_wait(sc); 763 1.1 tsutsui 764 1.1 tsutsui for (i = 0; i < 20; i++) { 765 1.1 tsutsui delay(30); 766 1.1 tsutsui 767 1.58 msaitoh data = bus_space_read_8(st, sh, MEC_PHY_DATA); 768 1.1 tsutsui 769 1.58 msaitoh if ((data & MEC_PHY_DATA_BUSY) == 0) { 770 1.58 msaitoh *val = data & MEC_PHY_DATA_VALUE; 771 1.58 msaitoh return 0; 772 1.58 msaitoh } 773 1.1 tsutsui } 774 1.58 msaitoh return -1; 775 1.1 tsutsui } 776 1.1 tsutsui 777 1.58 msaitoh static int 778 1.58 msaitoh mec_mii_writereg(device_t self, int phy, int reg, uint16_t val) 779 1.1 tsutsui { 780 1.19 tsutsui struct mec_softc *sc = device_private(self); 781 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 782 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 783 1.58 msaitoh int rv; 784 1.1 tsutsui 785 1.58 msaitoh if ((rv = mec_mii_wait(sc)) != 0) { 786 1.58 msaitoh printf("timed out writing %x: %hx\n", reg, val); 787 1.58 msaitoh return rv; 788 1.1 tsutsui } 789 1.1 tsutsui 790 1.7 tsutsui bus_space_write_8(st, sh, MEC_PHY_ADDRESS, 791 1.1 tsutsui (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); 792 1.1 tsutsui 793 1.1 tsutsui delay(60); 794 1.1 tsutsui 795 1.7 tsutsui bus_space_write_8(st, sh, MEC_PHY_DATA, val & MEC_PHY_DATA_VALUE); 796 1.1 tsutsui 797 1.1 tsutsui delay(60); 798 1.1 tsutsui 799 1.1 tsutsui mec_mii_wait(sc); 800 1.58 msaitoh 801 1.58 msaitoh return 0; 802 1.1 tsutsui } 803 1.1 tsutsui 804 1.19 tsutsui static int 805 1.1 tsutsui mec_mii_wait(struct mec_softc *sc) 806 1.1 tsutsui { 807 1.1 tsutsui uint32_t busy; 808 1.1 tsutsui int i, s; 809 1.1 tsutsui 810 1.1 tsutsui for (i = 0; i < 100; i++) { 811 1.1 tsutsui delay(30); 812 1.1 tsutsui 813 1.1 tsutsui s = splhigh(); 814 1.7 tsutsui busy = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_PHY_DATA); 815 1.1 tsutsui splx(s); 816 1.1 tsutsui 817 1.1 tsutsui if ((busy & MEC_PHY_DATA_BUSY) == 0) 818 1.1 tsutsui return 0; 819 1.12 macallan #if 0 820 1.1 tsutsui if (busy == 0xffff) /* XXX ? */ 821 1.1 tsutsui return 0; 822 1.12 macallan #endif 823 1.1 tsutsui } 824 1.1 tsutsui 825 1.19 tsutsui printf("%s: MII timed out\n", device_xname(sc->sc_dev)); 826 1.58 msaitoh return ETIMEDOUT; 827 1.1 tsutsui } 828 1.1 tsutsui 829 1.19 tsutsui static void 830 1.49 matt mec_statchg(struct ifnet *ifp) 831 1.1 tsutsui { 832 1.49 matt struct mec_softc *sc = ifp->if_softc; 833 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 834 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 835 1.1 tsutsui uint32_t control; 836 1.1 tsutsui 837 1.1 tsutsui control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); 838 1.1 tsutsui control &= ~(MEC_MAC_IPGT | MEC_MAC_IPGR1 | MEC_MAC_IPGR2 | 839 1.1 tsutsui MEC_MAC_FULL_DUPLEX | MEC_MAC_SPEED_SELECT); 840 1.1 tsutsui 841 1.1 tsutsui /* must also set IPG here for duplex stuff ... */ 842 1.1 tsutsui if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0) { 843 1.1 tsutsui control |= MEC_MAC_FULL_DUPLEX; 844 1.1 tsutsui } else { 845 1.1 tsutsui /* set IPG */ 846 1.1 tsutsui control |= MEC_MAC_IPG_DEFAULT; 847 1.1 tsutsui } 848 1.1 tsutsui 849 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); 850 1.1 tsutsui } 851 1.1 tsutsui 852 1.19 tsutsui static int 853 1.1 tsutsui mec_init(struct ifnet *ifp) 854 1.1 tsutsui { 855 1.1 tsutsui struct mec_softc *sc = ifp->if_softc; 856 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 857 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 858 1.1 tsutsui struct mec_rxdesc *rxd; 859 1.15 dyoung int i, rc; 860 1.1 tsutsui 861 1.1 tsutsui /* cancel any pending I/O */ 862 1.1 tsutsui mec_stop(ifp, 0); 863 1.1 tsutsui 864 1.1 tsutsui /* reset device */ 865 1.1 tsutsui mec_reset(sc); 866 1.1 tsutsui 867 1.1 tsutsui /* setup filter for multicast or promisc mode */ 868 1.1 tsutsui mec_setfilter(sc); 869 1.1 tsutsui 870 1.1 tsutsui /* set the TX ring pointer to the base address */ 871 1.1 tsutsui bus_space_write_8(st, sh, MEC_TX_RING_BASE, MEC_CDTXADDR(sc, 0)); 872 1.1 tsutsui 873 1.1 tsutsui sc->sc_txpending = 0; 874 1.1 tsutsui sc->sc_txdirty = 0; 875 1.1 tsutsui sc->sc_txlast = MEC_NTXDESC - 1; 876 1.1 tsutsui 877 1.1 tsutsui /* put RX buffers into FIFO */ 878 1.1 tsutsui for (i = 0; i < MEC_NRXDESC; i++) { 879 1.1 tsutsui rxd = &sc->sc_rxdesc[i]; 880 1.1 tsutsui rxd->rxd_stat = 0; 881 1.1 tsutsui MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); 882 1.1 tsutsui MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); 883 1.1 tsutsui bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); 884 1.1 tsutsui } 885 1.1 tsutsui sc->sc_rxptr = 0; 886 1.1 tsutsui 887 1.1 tsutsui #if 0 /* XXX no info */ 888 1.1 tsutsui bus_space_write_8(st, sh, MEC_TIMER, 0); 889 1.1 tsutsui #endif 890 1.1 tsutsui 891 1.1 tsutsui /* 892 1.1 tsutsui * MEC_DMA_TX_INT_ENABLE will be set later otherwise it causes 893 1.1 tsutsui * spurious interrupts when TX buffers are empty 894 1.1 tsutsui */ 895 1.1 tsutsui bus_space_write_8(st, sh, MEC_DMA_CONTROL, 896 1.1 tsutsui (MEC_RXD_DMAOFFSET << MEC_DMA_RX_DMA_OFFSET_SHIFT) | 897 1.1 tsutsui (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) | 898 1.1 tsutsui MEC_DMA_TX_DMA_ENABLE | /* MEC_DMA_TX_INT_ENABLE | */ 899 1.1 tsutsui MEC_DMA_RX_DMA_ENABLE | MEC_DMA_RX_INT_ENABLE); 900 1.1 tsutsui 901 1.1 tsutsui callout_reset(&sc->sc_tick_ch, hz, mec_tick, sc); 902 1.1 tsutsui 903 1.15 dyoung if ((rc = ether_mediachange(ifp)) != 0) 904 1.15 dyoung return rc; 905 1.15 dyoung 906 1.1 tsutsui ifp->if_flags |= IFF_RUNNING; 907 1.1 tsutsui mec_start(ifp); 908 1.1 tsutsui 909 1.1 tsutsui return 0; 910 1.1 tsutsui } 911 1.1 tsutsui 912 1.19 tsutsui static void 913 1.1 tsutsui mec_reset(struct mec_softc *sc) 914 1.1 tsutsui { 915 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 916 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 917 1.17 tsutsui uint64_t control; 918 1.17 tsutsui 919 1.17 tsutsui /* stop DMA first */ 920 1.17 tsutsui bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); 921 1.1 tsutsui 922 1.1 tsutsui /* reset chip */ 923 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, MEC_MAC_CORE_RESET); 924 1.8 tsutsui delay(1000); 925 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, 0); 926 1.1 tsutsui delay(1000); 927 1.1 tsutsui 928 1.14 tsutsui /* Default to 100/half and let auto-negotiation work its magic */ 929 1.1 tsutsui control = MEC_MAC_SPEED_SELECT | MEC_MAC_FILTER_MATCHMULTI | 930 1.1 tsutsui MEC_MAC_IPG_DEFAULT; 931 1.1 tsutsui 932 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); 933 1.17 tsutsui /* stop DMA again for sanity */ 934 1.1 tsutsui bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); 935 1.1 tsutsui 936 1.1 tsutsui DPRINTF(MEC_DEBUG_RESET, ("mec: control now %llx\n", 937 1.1 tsutsui bus_space_read_8(st, sh, MEC_MAC_CONTROL))); 938 1.1 tsutsui } 939 1.1 tsutsui 940 1.19 tsutsui static void 941 1.1 tsutsui mec_start(struct ifnet *ifp) 942 1.1 tsutsui { 943 1.1 tsutsui struct mec_softc *sc = ifp->if_softc; 944 1.1 tsutsui struct mbuf *m0, *m; 945 1.1 tsutsui struct mec_txdesc *txd; 946 1.1 tsutsui struct mec_txsoft *txs; 947 1.1 tsutsui bus_dmamap_t dmamap; 948 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 949 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 950 1.1 tsutsui int error, firsttx, nexttx, opending; 951 1.31 tsutsui int len, bufoff, buflen, nsegs, align, resid, pseg, nptr, slen, i; 952 1.31 tsutsui uint32_t txdcmd; 953 1.1 tsutsui 954 1.64 thorpej if ((ifp->if_flags & IFF_RUNNING) == 0) 955 1.1 tsutsui return; 956 1.1 tsutsui 957 1.1 tsutsui /* 958 1.1 tsutsui * Remember the previous txpending and the first transmit descriptor. 959 1.1 tsutsui */ 960 1.1 tsutsui opending = sc->sc_txpending; 961 1.1 tsutsui firsttx = MEC_NEXTTX(sc->sc_txlast); 962 1.1 tsutsui 963 1.1 tsutsui DPRINTF(MEC_DEBUG_START, 964 1.35 tsutsui ("%s: opending = %d, firsttx = %d\n", __func__, opending, firsttx)); 965 1.1 tsutsui 966 1.24 tsutsui while (sc->sc_txpending < MEC_NTXDESC - 1) { 967 1.1 tsutsui /* Grab a packet off the queue. */ 968 1.1 tsutsui IFQ_POLL(&ifp->if_snd, m0); 969 1.1 tsutsui if (m0 == NULL) 970 1.1 tsutsui break; 971 1.1 tsutsui m = NULL; 972 1.1 tsutsui 973 1.1 tsutsui /* 974 1.1 tsutsui * Get the next available transmit descriptor. 975 1.1 tsutsui */ 976 1.1 tsutsui nexttx = MEC_NEXTTX(sc->sc_txlast); 977 1.1 tsutsui txd = &sc->sc_txdesc[nexttx]; 978 1.1 tsutsui txs = &sc->sc_txsoft[nexttx]; 979 1.31 tsutsui dmamap = txs->txs_dmamap; 980 1.31 tsutsui txs->txs_flags = 0; 981 1.1 tsutsui 982 1.1 tsutsui buflen = 0; 983 1.1 tsutsui bufoff = 0; 984 1.31 tsutsui resid = 0; 985 1.31 tsutsui nptr = 0; /* XXX gcc */ 986 1.31 tsutsui pseg = 0; /* XXX gcc */ 987 1.1 tsutsui 988 1.1 tsutsui len = m0->m_pkthdr.len; 989 1.1 tsutsui 990 1.1 tsutsui DPRINTF(MEC_DEBUG_START, 991 1.35 tsutsui ("%s: len = %d, nexttx = %d, txpending = %d\n", 992 1.35 tsutsui __func__, len, nexttx, sc->sc_txpending)); 993 1.1 tsutsui 994 1.31 tsutsui if (len <= MEC_TXD_BUFSIZE) { 995 1.1 tsutsui /* 996 1.31 tsutsui * If a TX packet will fit into small txdesc buffer, 997 1.31 tsutsui * just copy it into there. Maybe it's faster than 998 1.31 tsutsui * checking alignment and calling bus_dma(9) etc. 999 1.1 tsutsui */ 1000 1.35 tsutsui DPRINTF(MEC_DEBUG_START, ("%s: short packet\n", 1001 1.35 tsutsui __func__)); 1002 1.1 tsutsui IFQ_DEQUEUE(&ifp->if_snd, m0); 1003 1.1 tsutsui 1004 1.31 tsutsui /* 1005 1.31 tsutsui * I don't know if MEC chip does auto padding, 1006 1.31 tsutsui * but do it manually for safety. 1007 1.31 tsutsui */ 1008 1.31 tsutsui if (len < ETHER_PAD_LEN) { 1009 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txdpad); 1010 1.31 tsutsui bufoff = MEC_TXD_BUFSTART(ETHER_PAD_LEN); 1011 1.31 tsutsui m_copydata(m0, 0, len, txd->txd_buf + bufoff); 1012 1.31 tsutsui memset(txd->txd_buf + bufoff + len, 0, 1013 1.31 tsutsui ETHER_PAD_LEN - len); 1014 1.31 tsutsui len = buflen = ETHER_PAD_LEN; 1015 1.31 tsutsui } else { 1016 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txdbuf); 1017 1.31 tsutsui bufoff = MEC_TXD_BUFSTART(len); 1018 1.31 tsutsui m_copydata(m0, 0, len, txd->txd_buf + bufoff); 1019 1.31 tsutsui buflen = len; 1020 1.31 tsutsui } 1021 1.1 tsutsui } else { 1022 1.1 tsutsui /* 1023 1.31 tsutsui * If the packet won't fit the static buffer in txdesc, 1024 1.31 tsutsui * we have to use the concatenate pointers to handle it. 1025 1.31 tsutsui */ 1026 1.35 tsutsui DPRINTF(MEC_DEBUG_START, ("%s: long packet\n", 1027 1.35 tsutsui __func__)); 1028 1.31 tsutsui txs->txs_flags = MEC_TXS_TXDPTR; 1029 1.1 tsutsui 1030 1.31 tsutsui /* 1031 1.31 tsutsui * Call bus_dmamap_load_mbuf(9) first to see 1032 1.31 tsutsui * how many chains the TX mbuf has. 1033 1.31 tsutsui */ 1034 1.31 tsutsui error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, 1035 1.31 tsutsui BUS_DMA_WRITE | BUS_DMA_NOWAIT); 1036 1.31 tsutsui if (error == 0) { 1037 1.31 tsutsui /* 1038 1.31 tsutsui * Check chains which might contain headers. 1039 1.31 tsutsui * They might be so much fragmented and 1040 1.31 tsutsui * it's better to copy them into txdesc buffer 1041 1.31 tsutsui * since they would be small enough. 1042 1.31 tsutsui */ 1043 1.31 tsutsui nsegs = dmamap->dm_nsegs; 1044 1.31 tsutsui for (pseg = 0; pseg < nsegs; pseg++) { 1045 1.31 tsutsui slen = dmamap->dm_segs[pseg].ds_len; 1046 1.31 tsutsui if (buflen + slen > 1047 1.31 tsutsui MEC_TXD_BUFSIZE1 - MEC_TXD_ALIGN) 1048 1.31 tsutsui break; 1049 1.31 tsutsui buflen += slen; 1050 1.31 tsutsui } 1051 1.31 tsutsui /* 1052 1.31 tsutsui * Check if the rest chains can be fit into 1053 1.31 tsutsui * the concatinate pointers. 1054 1.31 tsutsui */ 1055 1.31 tsutsui align = dmamap->dm_segs[pseg].ds_addr & 1056 1.31 tsutsui MEC_TXD_ALIGNMASK; 1057 1.31 tsutsui if (align > 0) { 1058 1.31 tsutsui /* 1059 1.31 tsutsui * If the first chain isn't uint64_t 1060 1.31 tsutsui * aligned, append the unaligned part 1061 1.31 tsutsui * into txdesc buffer too. 1062 1.31 tsutsui */ 1063 1.31 tsutsui resid = MEC_TXD_ALIGN - align; 1064 1.31 tsutsui buflen += resid; 1065 1.31 tsutsui for (; pseg < nsegs; pseg++) { 1066 1.31 tsutsui slen = 1067 1.31 tsutsui dmamap->dm_segs[pseg].ds_len; 1068 1.31 tsutsui if (slen > resid) 1069 1.31 tsutsui break; 1070 1.31 tsutsui resid -= slen; 1071 1.31 tsutsui } 1072 1.31 tsutsui } else if (pseg == 0) { 1073 1.31 tsutsui /* 1074 1.31 tsutsui * In this case, the first chain is 1075 1.31 tsutsui * uint64_t aligned but it's too long 1076 1.31 tsutsui * to put into txdesc buf. 1077 1.31 tsutsui * We have to put some data into 1078 1.31 tsutsui * txdesc buf even in this case, 1079 1.31 tsutsui * so put MEC_TXD_ALIGN bytes there. 1080 1.31 tsutsui */ 1081 1.31 tsutsui buflen = resid = MEC_TXD_ALIGN; 1082 1.31 tsutsui } 1083 1.31 tsutsui nptr = nsegs - pseg; 1084 1.31 tsutsui if (nptr <= MEC_NTXPTR) { 1085 1.31 tsutsui bufoff = MEC_TXD_BUFSTART(buflen); 1086 1.31 tsutsui 1087 1.31 tsutsui /* 1088 1.31 tsutsui * Check if all the rest chains are 1089 1.31 tsutsui * uint64_t aligned. 1090 1.31 tsutsui */ 1091 1.31 tsutsui align = 0; 1092 1.31 tsutsui for (i = pseg + 1; i < nsegs; i++) 1093 1.31 tsutsui align |= 1094 1.31 tsutsui dmamap->dm_segs[i].ds_addr 1095 1.31 tsutsui & MEC_TXD_ALIGNMASK; 1096 1.31 tsutsui if (align != 0) { 1097 1.31 tsutsui /* chains are not aligned */ 1098 1.31 tsutsui error = -1; 1099 1.31 tsutsui } 1100 1.31 tsutsui } else { 1101 1.31 tsutsui /* The TX mbuf chains doesn't fit. */ 1102 1.31 tsutsui error = -1; 1103 1.31 tsutsui } 1104 1.31 tsutsui if (error == -1) 1105 1.31 tsutsui bus_dmamap_unload(sc->sc_dmat, dmamap); 1106 1.31 tsutsui } 1107 1.31 tsutsui if (error != 0) { 1108 1.31 tsutsui /* 1109 1.31 tsutsui * The TX mbuf chains can't be put into 1110 1.31 tsutsui * the concatinate buffers. In this case, 1111 1.31 tsutsui * we have to allocate a new contiguous mbuf 1112 1.31 tsutsui * and copy data into it. 1113 1.31 tsutsui * 1114 1.31 tsutsui * Even in this case, the Ethernet header in 1115 1.31 tsutsui * the TX mbuf might be unaligned and trailing 1116 1.31 tsutsui * data might be word aligned, so put 2 byte 1117 1.31 tsutsui * (MEC_ETHER_ALIGN) padding at the top of the 1118 1.31 tsutsui * allocated mbuf and copy TX packets. 1119 1.31 tsutsui * 6 bytes (MEC_ALIGN_BYTES - MEC_ETHER_ALIGN) 1120 1.31 tsutsui * at the top of the new mbuf won't be uint64_t 1121 1.31 tsutsui * alignd, but we have to put some data into 1122 1.31 tsutsui * txdesc buffer anyway even if the buffer 1123 1.31 tsutsui * is uint64_t aligned. 1124 1.59 msaitoh */ 1125 1.59 msaitoh DPRINTF(MEC_DEBUG_START | MEC_DEBUG_TXSEGS, 1126 1.35 tsutsui ("%s: re-allocating mbuf\n", __func__)); 1127 1.31 tsutsui 1128 1.1 tsutsui MGETHDR(m, M_DONTWAIT, MT_DATA); 1129 1.1 tsutsui if (m == NULL) { 1130 1.1 tsutsui printf("%s: unable to allocate " 1131 1.19 tsutsui "TX mbuf\n", 1132 1.19 tsutsui device_xname(sc->sc_dev)); 1133 1.1 tsutsui break; 1134 1.1 tsutsui } 1135 1.1 tsutsui if (len > (MHLEN - MEC_ETHER_ALIGN)) { 1136 1.1 tsutsui MCLGET(m, M_DONTWAIT); 1137 1.1 tsutsui if ((m->m_flags & M_EXT) == 0) { 1138 1.1 tsutsui printf("%s: unable to allocate " 1139 1.1 tsutsui "TX cluster\n", 1140 1.19 tsutsui device_xname(sc->sc_dev)); 1141 1.1 tsutsui m_freem(m); 1142 1.1 tsutsui break; 1143 1.1 tsutsui } 1144 1.1 tsutsui } 1145 1.31 tsutsui m->m_data += MEC_ETHER_ALIGN; 1146 1.31 tsutsui 1147 1.1 tsutsui /* 1148 1.31 tsutsui * Copy whole data (including unaligned part) 1149 1.31 tsutsui * for following bpf_mtap(). 1150 1.1 tsutsui */ 1151 1.10 christos m_copydata(m0, 0, len, mtod(m, void *)); 1152 1.1 tsutsui m->m_pkthdr.len = m->m_len = len; 1153 1.1 tsutsui error = bus_dmamap_load_mbuf(sc->sc_dmat, 1154 1.1 tsutsui dmamap, m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); 1155 1.31 tsutsui if (dmamap->dm_nsegs > 1) { 1156 1.31 tsutsui /* should not happen, but for sanity */ 1157 1.31 tsutsui bus_dmamap_unload(sc->sc_dmat, dmamap); 1158 1.31 tsutsui error = -1; 1159 1.31 tsutsui } 1160 1.31 tsutsui if (error != 0) { 1161 1.1 tsutsui printf("%s: unable to load TX buffer, " 1162 1.1 tsutsui "error = %d\n", 1163 1.19 tsutsui device_xname(sc->sc_dev), error); 1164 1.30 tsutsui m_freem(m); 1165 1.1 tsutsui break; 1166 1.1 tsutsui } 1167 1.31 tsutsui /* 1168 1.31 tsutsui * Only the first segment should be put into 1169 1.31 tsutsui * the concatinate pointer in this case. 1170 1.31 tsutsui */ 1171 1.31 tsutsui pseg = 0; 1172 1.31 tsutsui nptr = 1; 1173 1.31 tsutsui 1174 1.31 tsutsui /* 1175 1.62 msaitoh * Set length of unaligned part which will be 1176 1.31 tsutsui * copied into txdesc buffer. 1177 1.31 tsutsui */ 1178 1.31 tsutsui buflen = MEC_TXD_ALIGN - MEC_ETHER_ALIGN; 1179 1.31 tsutsui bufoff = MEC_TXD_BUFSTART(buflen); 1180 1.31 tsutsui resid = buflen; 1181 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 1182 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbuf); 1183 1.31 tsutsui if (len <= 160) 1184 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbufa); 1185 1.31 tsutsui else if (len <= 256) 1186 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbufb); 1187 1.31 tsutsui else if (len <= 512) 1188 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbufc); 1189 1.31 tsutsui else if (len <= 1024) 1190 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbufd); 1191 1.31 tsutsui else 1192 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txmbufe); 1193 1.31 tsutsui #endif 1194 1.31 tsutsui } 1195 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 1196 1.31 tsutsui else { 1197 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrs); 1198 1.31 tsutsui if (nptr == 1) { 1199 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptr1); 1200 1.31 tsutsui if (len <= 160) 1201 1.31 tsutsui MEC_EVCNT_INCR( 1202 1.31 tsutsui &sc->sc_ev_txptr1a); 1203 1.31 tsutsui else if (len <= 256) 1204 1.31 tsutsui MEC_EVCNT_INCR( 1205 1.31 tsutsui &sc->sc_ev_txptr1b); 1206 1.31 tsutsui else if (len <= 512) 1207 1.31 tsutsui MEC_EVCNT_INCR( 1208 1.31 tsutsui &sc->sc_ev_txptr1c); 1209 1.31 tsutsui else if (len <= 1024) 1210 1.31 tsutsui MEC_EVCNT_INCR( 1211 1.31 tsutsui &sc->sc_ev_txptr1d); 1212 1.31 tsutsui else 1213 1.31 tsutsui MEC_EVCNT_INCR( 1214 1.31 tsutsui &sc->sc_ev_txptr1e); 1215 1.31 tsutsui } else if (nptr == 2) { 1216 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptr2); 1217 1.31 tsutsui if (len <= 160) 1218 1.31 tsutsui MEC_EVCNT_INCR( 1219 1.31 tsutsui &sc->sc_ev_txptr2a); 1220 1.31 tsutsui else if (len <= 256) 1221 1.31 tsutsui MEC_EVCNT_INCR( 1222 1.31 tsutsui &sc->sc_ev_txptr2b); 1223 1.31 tsutsui else if (len <= 512) 1224 1.31 tsutsui MEC_EVCNT_INCR( 1225 1.31 tsutsui &sc->sc_ev_txptr2c); 1226 1.31 tsutsui else if (len <= 1024) 1227 1.31 tsutsui MEC_EVCNT_INCR( 1228 1.31 tsutsui &sc->sc_ev_txptr2d); 1229 1.31 tsutsui else 1230 1.31 tsutsui MEC_EVCNT_INCR( 1231 1.31 tsutsui &sc->sc_ev_txptr2e); 1232 1.31 tsutsui } else if (nptr == 3) { 1233 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptr3); 1234 1.31 tsutsui if (len <= 160) 1235 1.31 tsutsui MEC_EVCNT_INCR( 1236 1.31 tsutsui &sc->sc_ev_txptr3a); 1237 1.31 tsutsui else if (len <= 256) 1238 1.31 tsutsui MEC_EVCNT_INCR( 1239 1.31 tsutsui &sc->sc_ev_txptr3b); 1240 1.31 tsutsui else if (len <= 512) 1241 1.31 tsutsui MEC_EVCNT_INCR( 1242 1.31 tsutsui &sc->sc_ev_txptr3c); 1243 1.31 tsutsui else if (len <= 1024) 1244 1.31 tsutsui MEC_EVCNT_INCR( 1245 1.31 tsutsui &sc->sc_ev_txptr3d); 1246 1.31 tsutsui else 1247 1.31 tsutsui MEC_EVCNT_INCR( 1248 1.31 tsutsui &sc->sc_ev_txptr3e); 1249 1.31 tsutsui } 1250 1.31 tsutsui if (pseg == 0) 1251 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc0); 1252 1.31 tsutsui else if (pseg == 1) 1253 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc1); 1254 1.31 tsutsui else if (pseg == 2) 1255 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc2); 1256 1.31 tsutsui else if (pseg == 3) 1257 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc3); 1258 1.31 tsutsui else if (pseg == 4) 1259 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc4); 1260 1.31 tsutsui else if (pseg == 5) 1261 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc5); 1262 1.31 tsutsui else 1263 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrc6); 1264 1.31 tsutsui if (buflen <= 8) 1265 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh0); 1266 1.31 tsutsui else if (buflen <= 16) 1267 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh1); 1268 1.31 tsutsui else if (buflen <= 32) 1269 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh2); 1270 1.31 tsutsui else if (buflen <= 64) 1271 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh3); 1272 1.31 tsutsui else if (buflen <= 80) 1273 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh4); 1274 1.31 tsutsui else 1275 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txptrh5); 1276 1.1 tsutsui } 1277 1.31 tsutsui #endif 1278 1.31 tsutsui m_copydata(m0, 0, buflen, txd->txd_buf + bufoff); 1279 1.31 tsutsui 1280 1.1 tsutsui IFQ_DEQUEUE(&ifp->if_snd, m0); 1281 1.1 tsutsui if (m != NULL) { 1282 1.1 tsutsui m_freem(m0); 1283 1.1 tsutsui m0 = m; 1284 1.1 tsutsui } 1285 1.1 tsutsui 1286 1.1 tsutsui /* 1287 1.1 tsutsui * sync the DMA map for TX mbuf 1288 1.1 tsutsui */ 1289 1.31 tsutsui bus_dmamap_sync(sc->sc_dmat, dmamap, buflen, 1290 1.31 tsutsui len - buflen, BUS_DMASYNC_PREWRITE); 1291 1.1 tsutsui } 1292 1.1 tsutsui 1293 1.1 tsutsui /* 1294 1.1 tsutsui * Pass packet to bpf if there is a listener. 1295 1.1 tsutsui */ 1296 1.57 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 1297 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txpkts); 1298 1.1 tsutsui 1299 1.1 tsutsui /* 1300 1.1 tsutsui * setup the transmit descriptor. 1301 1.1 tsutsui */ 1302 1.31 tsutsui txdcmd = TXCMD_BUFSTART(MEC_TXDESCSIZE - buflen) | (len - 1); 1303 1.1 tsutsui 1304 1.29 tsutsui /* 1305 1.29 tsutsui * Set MEC_TXCMD_TXINT every MEC_NTXDESC_INTR packets 1306 1.29 tsutsui * if more than half txdescs have been queued 1307 1.29 tsutsui * because TX_EMPTY interrupts will rarely happen 1308 1.29 tsutsui * if TX queue is so stacked. 1309 1.29 tsutsui */ 1310 1.29 tsutsui if (sc->sc_txpending > (MEC_NTXDESC / 2) && 1311 1.29 tsutsui (nexttx & (MEC_NTXDESC_INTR - 1)) == 0) 1312 1.31 tsutsui txdcmd |= MEC_TXCMD_TXINT; 1313 1.31 tsutsui 1314 1.31 tsutsui if ((txs->txs_flags & MEC_TXS_TXDPTR) != 0) { 1315 1.31 tsutsui bus_dma_segment_t *segs = dmamap->dm_segs; 1316 1.1 tsutsui 1317 1.31 tsutsui DPRINTF(MEC_DEBUG_TXSEGS, 1318 1.35 tsutsui ("%s: nsegs = %d, pseg = %d, nptr = %d\n", 1319 1.35 tsutsui __func__, dmamap->dm_nsegs, pseg, nptr)); 1320 1.31 tsutsui 1321 1.31 tsutsui switch (nptr) { 1322 1.31 tsutsui case 3: 1323 1.31 tsutsui KASSERT((segs[pseg + 2].ds_addr & 1324 1.31 tsutsui MEC_TXD_ALIGNMASK) == 0); 1325 1.31 tsutsui txdcmd |= MEC_TXCMD_PTR3; 1326 1.31 tsutsui txd->txd_ptr[2] = 1327 1.31 tsutsui TXPTR_LEN(segs[pseg + 2].ds_len - 1) | 1328 1.31 tsutsui segs[pseg + 2].ds_addr; 1329 1.31 tsutsui /* FALLTHROUGH */ 1330 1.31 tsutsui case 2: 1331 1.31 tsutsui KASSERT((segs[pseg + 1].ds_addr & 1332 1.31 tsutsui MEC_TXD_ALIGNMASK) == 0); 1333 1.31 tsutsui txdcmd |= MEC_TXCMD_PTR2; 1334 1.31 tsutsui txd->txd_ptr[1] = 1335 1.31 tsutsui TXPTR_LEN(segs[pseg + 1].ds_len - 1) | 1336 1.31 tsutsui segs[pseg + 1].ds_addr; 1337 1.31 tsutsui /* FALLTHROUGH */ 1338 1.31 tsutsui case 1: 1339 1.31 tsutsui txdcmd |= MEC_TXCMD_PTR1; 1340 1.31 tsutsui txd->txd_ptr[0] = 1341 1.31 tsutsui TXPTR_LEN(segs[pseg].ds_len - resid - 1) | 1342 1.31 tsutsui (segs[pseg].ds_addr + resid); 1343 1.31 tsutsui break; 1344 1.31 tsutsui default: 1345 1.31 tsutsui panic("%s: impossible nptr in %s", 1346 1.31 tsutsui device_xname(sc->sc_dev), __func__); 1347 1.31 tsutsui /* NOTREACHED */ 1348 1.31 tsutsui } 1349 1.1 tsutsui /* 1350 1.1 tsutsui * Store a pointer to the packet so we can 1351 1.1 tsutsui * free it later. 1352 1.1 tsutsui */ 1353 1.1 tsutsui txs->txs_mbuf = m0; 1354 1.1 tsutsui } else { 1355 1.1 tsutsui /* 1356 1.1 tsutsui * In this case all data are copied to buffer in txdesc, 1357 1.1 tsutsui * we can free TX mbuf here. 1358 1.1 tsutsui */ 1359 1.1 tsutsui m_freem(m0); 1360 1.1 tsutsui } 1361 1.31 tsutsui txd->txd_cmd = txdcmd; 1362 1.1 tsutsui 1363 1.1 tsutsui DPRINTF(MEC_DEBUG_START, 1364 1.35 tsutsui ("%s: txd_cmd = 0x%016llx\n", 1365 1.35 tsutsui __func__, txd->txd_cmd)); 1366 1.31 tsutsui DPRINTF(MEC_DEBUG_START, 1367 1.35 tsutsui ("%s: txd_ptr[0] = 0x%016llx\n", 1368 1.35 tsutsui __func__, txd->txd_ptr[0])); 1369 1.31 tsutsui DPRINTF(MEC_DEBUG_START, 1370 1.35 tsutsui ("%s: txd_ptr[1] = 0x%016llx\n", 1371 1.35 tsutsui __func__, txd->txd_ptr[1])); 1372 1.31 tsutsui DPRINTF(MEC_DEBUG_START, 1373 1.35 tsutsui ("%s: txd_ptr[2] = 0x%016llx\n", 1374 1.35 tsutsui __func__, txd->txd_ptr[2])); 1375 1.1 tsutsui DPRINTF(MEC_DEBUG_START, 1376 1.35 tsutsui ("%s: len = %d (0x%04x), buflen = %d (0x%02x)\n", 1377 1.35 tsutsui __func__, len, len, buflen, buflen)); 1378 1.1 tsutsui 1379 1.1 tsutsui /* sync TX descriptor */ 1380 1.1 tsutsui MEC_TXDESCSYNC(sc, nexttx, 1381 1.59 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1382 1.1 tsutsui 1383 1.25 tsutsui /* start TX */ 1384 1.25 tsutsui bus_space_write_8(st, sh, MEC_TX_RING_PTR, MEC_NEXTTX(nexttx)); 1385 1.25 tsutsui 1386 1.1 tsutsui /* advance the TX pointer. */ 1387 1.1 tsutsui sc->sc_txpending++; 1388 1.1 tsutsui sc->sc_txlast = nexttx; 1389 1.1 tsutsui } 1390 1.1 tsutsui 1391 1.23 tsutsui if (sc->sc_txpending == MEC_NTXDESC - 1) { 1392 1.64 thorpej /* No more slots. */ 1393 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txdstall); 1394 1.1 tsutsui } 1395 1.1 tsutsui 1396 1.1 tsutsui if (sc->sc_txpending != opending) { 1397 1.1 tsutsui /* 1398 1.1 tsutsui * If the transmitter was idle, 1399 1.14 tsutsui * reset the txdirty pointer and re-enable TX interrupt. 1400 1.1 tsutsui */ 1401 1.1 tsutsui if (opending == 0) { 1402 1.1 tsutsui sc->sc_txdirty = firsttx; 1403 1.1 tsutsui bus_space_write_8(st, sh, MEC_TX_ALIAS, 1404 1.1 tsutsui MEC_TX_ALIAS_INT_ENABLE); 1405 1.1 tsutsui } 1406 1.1 tsutsui 1407 1.1 tsutsui /* Set a watchdog timer in case the chip flakes out. */ 1408 1.1 tsutsui ifp->if_timer = 5; 1409 1.1 tsutsui } 1410 1.1 tsutsui } 1411 1.1 tsutsui 1412 1.19 tsutsui static void 1413 1.1 tsutsui mec_stop(struct ifnet *ifp, int disable) 1414 1.1 tsutsui { 1415 1.1 tsutsui struct mec_softc *sc = ifp->if_softc; 1416 1.1 tsutsui struct mec_txsoft *txs; 1417 1.1 tsutsui int i; 1418 1.1 tsutsui 1419 1.35 tsutsui DPRINTF(MEC_DEBUG_STOP, ("%s\n", __func__)); 1420 1.1 tsutsui 1421 1.1 tsutsui ifp->if_timer = 0; 1422 1.64 thorpej ifp->if_flags &= ~IFF_RUNNING; 1423 1.1 tsutsui 1424 1.1 tsutsui callout_stop(&sc->sc_tick_ch); 1425 1.1 tsutsui mii_down(&sc->sc_mii); 1426 1.1 tsutsui 1427 1.1 tsutsui /* release any TX buffers */ 1428 1.1 tsutsui for (i = 0; i < MEC_NTXDESC; i++) { 1429 1.1 tsutsui txs = &sc->sc_txsoft[i]; 1430 1.31 tsutsui if ((txs->txs_flags & MEC_TXS_TXDPTR) != 0) { 1431 1.1 tsutsui bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); 1432 1.1 tsutsui m_freem(txs->txs_mbuf); 1433 1.1 tsutsui txs->txs_mbuf = NULL; 1434 1.1 tsutsui } 1435 1.1 tsutsui } 1436 1.1 tsutsui } 1437 1.1 tsutsui 1438 1.19 tsutsui static int 1439 1.10 christos mec_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1440 1.1 tsutsui { 1441 1.1 tsutsui int s, error; 1442 1.1 tsutsui 1443 1.1 tsutsui s = splnet(); 1444 1.1 tsutsui 1445 1.15 dyoung error = ether_ioctl(ifp, cmd, data); 1446 1.15 dyoung if (error == ENETRESET) { 1447 1.15 dyoung /* 1448 1.15 dyoung * Multicast list has changed; set the hardware filter 1449 1.15 dyoung * accordingly. 1450 1.15 dyoung */ 1451 1.15 dyoung if (ifp->if_flags & IFF_RUNNING) 1452 1.15 dyoung error = mec_init(ifp); 1453 1.15 dyoung else 1454 1.15 dyoung error = 0; 1455 1.1 tsutsui } 1456 1.1 tsutsui 1457 1.1 tsutsui /* Try to get more packets going. */ 1458 1.1 tsutsui mec_start(ifp); 1459 1.1 tsutsui 1460 1.1 tsutsui splx(s); 1461 1.1 tsutsui return error; 1462 1.1 tsutsui } 1463 1.1 tsutsui 1464 1.19 tsutsui static void 1465 1.1 tsutsui mec_watchdog(struct ifnet *ifp) 1466 1.1 tsutsui { 1467 1.1 tsutsui struct mec_softc *sc = ifp->if_softc; 1468 1.1 tsutsui 1469 1.19 tsutsui printf("%s: device timeout\n", device_xname(sc->sc_dev)); 1470 1.63 thorpej if_statinc(ifp, if_oerrors); 1471 1.1 tsutsui 1472 1.1 tsutsui mec_init(ifp); 1473 1.1 tsutsui } 1474 1.1 tsutsui 1475 1.19 tsutsui static void 1476 1.1 tsutsui mec_tick(void *arg) 1477 1.1 tsutsui { 1478 1.1 tsutsui struct mec_softc *sc = arg; 1479 1.1 tsutsui int s; 1480 1.1 tsutsui 1481 1.1 tsutsui s = splnet(); 1482 1.1 tsutsui mii_tick(&sc->sc_mii); 1483 1.1 tsutsui splx(s); 1484 1.1 tsutsui 1485 1.1 tsutsui callout_reset(&sc->sc_tick_ch, hz, mec_tick, sc); 1486 1.1 tsutsui } 1487 1.1 tsutsui 1488 1.19 tsutsui static void 1489 1.1 tsutsui mec_setfilter(struct mec_softc *sc) 1490 1.1 tsutsui { 1491 1.1 tsutsui struct ethercom *ec = &sc->sc_ethercom; 1492 1.1 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1493 1.1 tsutsui struct ether_multi *enm; 1494 1.1 tsutsui struct ether_multistep step; 1495 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 1496 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 1497 1.1 tsutsui uint64_t mchash; 1498 1.1 tsutsui uint32_t control, hash; 1499 1.1 tsutsui int mcnt; 1500 1.1 tsutsui 1501 1.1 tsutsui control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); 1502 1.1 tsutsui control &= ~MEC_MAC_FILTER_MASK; 1503 1.1 tsutsui 1504 1.1 tsutsui if (ifp->if_flags & IFF_PROMISC) { 1505 1.1 tsutsui control |= MEC_MAC_FILTER_PROMISC; 1506 1.1 tsutsui bus_space_write_8(st, sh, MEC_MULTICAST, 0xffffffffffffffffULL); 1507 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); 1508 1.1 tsutsui return; 1509 1.1 tsutsui } 1510 1.1 tsutsui 1511 1.1 tsutsui mcnt = 0; 1512 1.1 tsutsui mchash = 0; 1513 1.60 msaitoh ETHER_LOCK(ec); 1514 1.1 tsutsui ETHER_FIRST_MULTI(step, ec, enm); 1515 1.1 tsutsui while (enm != NULL) { 1516 1.1 tsutsui if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 1517 1.1 tsutsui /* set allmulti for a range of multicast addresses */ 1518 1.1 tsutsui control |= MEC_MAC_FILTER_ALLMULTI; 1519 1.1 tsutsui bus_space_write_8(st, sh, MEC_MULTICAST, 1520 1.1 tsutsui 0xffffffffffffffffULL); 1521 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); 1522 1.60 msaitoh ETHER_UNLOCK(ec); 1523 1.1 tsutsui return; 1524 1.1 tsutsui } 1525 1.1 tsutsui 1526 1.1 tsutsui #define mec_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) 1527 1.1 tsutsui 1528 1.1 tsutsui hash = mec_calchash(enm->enm_addrlo); 1529 1.1 tsutsui mchash |= 1 << hash; 1530 1.1 tsutsui mcnt++; 1531 1.1 tsutsui ETHER_NEXT_MULTI(step, enm); 1532 1.1 tsutsui } 1533 1.60 msaitoh ETHER_UNLOCK(ec); 1534 1.1 tsutsui 1535 1.1 tsutsui ifp->if_flags &= ~IFF_ALLMULTI; 1536 1.1 tsutsui 1537 1.1 tsutsui if (mcnt > 0) 1538 1.1 tsutsui control |= MEC_MAC_FILTER_MATCHMULTI; 1539 1.1 tsutsui 1540 1.1 tsutsui bus_space_write_8(st, sh, MEC_MULTICAST, mchash); 1541 1.1 tsutsui bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); 1542 1.1 tsutsui } 1543 1.1 tsutsui 1544 1.19 tsutsui static int 1545 1.1 tsutsui mec_intr(void *arg) 1546 1.1 tsutsui { 1547 1.1 tsutsui struct mec_softc *sc = arg; 1548 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 1549 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 1550 1.1 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1551 1.21 tsutsui uint32_t statreg, statack, txptr; 1552 1.1 tsutsui int handled, sent; 1553 1.1 tsutsui 1554 1.35 tsutsui DPRINTF(MEC_DEBUG_INTR, ("%s: called\n", __func__)); 1555 1.1 tsutsui 1556 1.1 tsutsui handled = sent = 0; 1557 1.1 tsutsui 1558 1.1 tsutsui for (;;) { 1559 1.1 tsutsui statreg = bus_space_read_8(st, sh, MEC_INT_STATUS); 1560 1.1 tsutsui 1561 1.1 tsutsui DPRINTF(MEC_DEBUG_INTR, 1562 1.35 tsutsui ("%s: INT_STAT = 0x%08x\n", __func__, statreg)); 1563 1.1 tsutsui 1564 1.1 tsutsui statack = statreg & MEC_INT_STATUS_MASK; 1565 1.1 tsutsui if (statack == 0) 1566 1.1 tsutsui break; 1567 1.1 tsutsui bus_space_write_8(st, sh, MEC_INT_STATUS, statack); 1568 1.1 tsutsui 1569 1.1 tsutsui handled = 1; 1570 1.1 tsutsui 1571 1.1 tsutsui if (statack & 1572 1.1 tsutsui (MEC_INT_RX_THRESHOLD | 1573 1.1 tsutsui MEC_INT_RX_FIFO_UNDERFLOW)) { 1574 1.1 tsutsui mec_rxintr(sc); 1575 1.1 tsutsui } 1576 1.1 tsutsui 1577 1.1 tsutsui if (statack & 1578 1.1 tsutsui (MEC_INT_TX_EMPTY | 1579 1.1 tsutsui MEC_INT_TX_PACKET_SENT | 1580 1.1 tsutsui MEC_INT_TX_ABORT)) { 1581 1.21 tsutsui txptr = (statreg & MEC_INT_TX_RING_BUFFER_ALIAS) 1582 1.21 tsutsui >> MEC_INT_TX_RING_BUFFER_SHIFT; 1583 1.21 tsutsui mec_txintr(sc, txptr); 1584 1.1 tsutsui sent = 1; 1585 1.21 tsutsui if ((statack & MEC_INT_TX_EMPTY) != 0) { 1586 1.1 tsutsui /* 1587 1.1 tsutsui * disable TX interrupt to stop 1588 1.1 tsutsui * TX empty interrupt 1589 1.1 tsutsui */ 1590 1.1 tsutsui bus_space_write_8(st, sh, MEC_TX_ALIAS, 0); 1591 1.1 tsutsui DPRINTF(MEC_DEBUG_INTR, 1592 1.35 tsutsui ("%s: disable TX_INT\n", __func__)); 1593 1.1 tsutsui } 1594 1.31 tsutsui #ifdef MEC_EVENT_COUNTERS 1595 1.31 tsutsui if ((statack & MEC_INT_TX_EMPTY) != 0) 1596 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txempty); 1597 1.31 tsutsui if ((statack & MEC_INT_TX_PACKET_SENT) != 0) 1598 1.31 tsutsui MEC_EVCNT_INCR(&sc->sc_ev_txsent); 1599 1.31 tsutsui #endif 1600 1.1 tsutsui } 1601 1.1 tsutsui 1602 1.1 tsutsui if (statack & 1603 1.1 tsutsui (MEC_INT_TX_LINK_FAIL | 1604 1.1 tsutsui MEC_INT_TX_MEM_ERROR | 1605 1.1 tsutsui MEC_INT_TX_ABORT | 1606 1.1 tsutsui MEC_INT_RX_DMA_UNDERFLOW)) { 1607 1.35 tsutsui printf("%s: %s: interrupt status = 0x%08x\n", 1608 1.35 tsutsui device_xname(sc->sc_dev), __func__, statreg); 1609 1.26 tsutsui mec_init(ifp); 1610 1.26 tsutsui break; 1611 1.1 tsutsui } 1612 1.1 tsutsui } 1613 1.1 tsutsui 1614 1.54 ozaki if (sent) { 1615 1.1 tsutsui /* try to get more packets going */ 1616 1.54 ozaki if_schedule_deferred_start(ifp); 1617 1.1 tsutsui } 1618 1.1 tsutsui 1619 1.1 tsutsui if (handled) 1620 1.1 tsutsui rnd_add_uint32(&sc->sc_rnd_source, statreg); 1621 1.1 tsutsui 1622 1.1 tsutsui return handled; 1623 1.1 tsutsui } 1624 1.1 tsutsui 1625 1.19 tsutsui static void 1626 1.1 tsutsui mec_rxintr(struct mec_softc *sc) 1627 1.1 tsutsui { 1628 1.1 tsutsui bus_space_tag_t st = sc->sc_st; 1629 1.1 tsutsui bus_space_handle_t sh = sc->sc_sh; 1630 1.1 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1631 1.1 tsutsui struct mbuf *m; 1632 1.1 tsutsui struct mec_rxdesc *rxd; 1633 1.1 tsutsui uint64_t rxstat; 1634 1.1 tsutsui u_int len; 1635 1.1 tsutsui int i; 1636 1.34 tsutsui uint32_t crc; 1637 1.1 tsutsui 1638 1.35 tsutsui DPRINTF(MEC_DEBUG_RXINTR, ("%s: called\n", __func__)); 1639 1.1 tsutsui 1640 1.1 tsutsui for (i = sc->sc_rxptr;; i = MEC_NEXTRX(i)) { 1641 1.1 tsutsui rxd = &sc->sc_rxdesc[i]; 1642 1.1 tsutsui 1643 1.1 tsutsui MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_POSTREAD); 1644 1.1 tsutsui rxstat = rxd->rxd_stat; 1645 1.1 tsutsui 1646 1.1 tsutsui DPRINTF(MEC_DEBUG_RXINTR, 1647 1.35 tsutsui ("%s: rxstat = 0x%016llx, rxptr = %d\n", 1648 1.35 tsutsui __func__, rxstat, i)); 1649 1.35 tsutsui DPRINTF(MEC_DEBUG_RXINTR, ("%s: rxfifo = 0x%08x\n", 1650 1.35 tsutsui __func__, (u_int)bus_space_read_8(st, sh, MEC_RX_FIFO))); 1651 1.1 tsutsui 1652 1.1 tsutsui if ((rxstat & MEC_RXSTAT_RECEIVED) == 0) { 1653 1.1 tsutsui MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); 1654 1.1 tsutsui break; 1655 1.1 tsutsui } 1656 1.1 tsutsui 1657 1.1 tsutsui len = rxstat & MEC_RXSTAT_LEN; 1658 1.1 tsutsui 1659 1.1 tsutsui if (len < ETHER_MIN_LEN || 1660 1.9 tsutsui len > (MCLBYTES - MEC_ETHER_ALIGN)) { 1661 1.1 tsutsui /* invalid length packet; drop it. */ 1662 1.1 tsutsui DPRINTF(MEC_DEBUG_RXINTR, 1663 1.35 tsutsui ("%s: wrong packet\n", __func__)); 1664 1.1 tsutsui dropit: 1665 1.63 thorpej if_statinc(ifp, if_ierrors); 1666 1.1 tsutsui rxd->rxd_stat = 0; 1667 1.1 tsutsui MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); 1668 1.1 tsutsui bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, 1669 1.1 tsutsui MEC_CDRXADDR(sc, i)); 1670 1.1 tsutsui continue; 1671 1.1 tsutsui } 1672 1.1 tsutsui 1673 1.33 tsutsui /* 1674 1.40 tsutsui * If 802.1Q VLAN MTU is enabled, ignore the bad packet error. 1675 1.33 tsutsui */ 1676 1.33 tsutsui if ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) != 0) 1677 1.33 tsutsui rxstat &= ~MEC_RXSTAT_BADPACKET; 1678 1.33 tsutsui 1679 1.1 tsutsui if (rxstat & 1680 1.1 tsutsui (MEC_RXSTAT_BADPACKET | 1681 1.1 tsutsui MEC_RXSTAT_LONGEVENT | 1682 1.1 tsutsui MEC_RXSTAT_INVALID | 1683 1.1 tsutsui MEC_RXSTAT_CRCERROR | 1684 1.1 tsutsui MEC_RXSTAT_VIOLATION)) { 1685 1.41 matt printf("%s: mec_rxintr: status = 0x%016"PRIx64"\n", 1686 1.41 matt device_xname(sc->sc_dev), rxstat); 1687 1.1 tsutsui goto dropit; 1688 1.1 tsutsui } 1689 1.1 tsutsui 1690 1.1 tsutsui /* 1691 1.4 thorpej * The MEC includes the CRC with every packet. Trim 1692 1.4 thorpej * it off here. 1693 1.4 thorpej */ 1694 1.4 thorpej len -= ETHER_CRC_LEN; 1695 1.4 thorpej 1696 1.4 thorpej /* 1697 1.1 tsutsui * now allocate an mbuf (and possibly a cluster) to hold 1698 1.1 tsutsui * the received packet. 1699 1.1 tsutsui */ 1700 1.1 tsutsui MGETHDR(m, M_DONTWAIT, MT_DATA); 1701 1.1 tsutsui if (m == NULL) { 1702 1.1 tsutsui printf("%s: unable to allocate RX mbuf\n", 1703 1.19 tsutsui device_xname(sc->sc_dev)); 1704 1.1 tsutsui goto dropit; 1705 1.1 tsutsui } 1706 1.1 tsutsui if (len > (MHLEN - MEC_ETHER_ALIGN)) { 1707 1.1 tsutsui MCLGET(m, M_DONTWAIT); 1708 1.1 tsutsui if ((m->m_flags & M_EXT) == 0) { 1709 1.1 tsutsui printf("%s: unable to allocate RX cluster\n", 1710 1.19 tsutsui device_xname(sc->sc_dev)); 1711 1.1 tsutsui m_freem(m); 1712 1.1 tsutsui m = NULL; 1713 1.1 tsutsui goto dropit; 1714 1.1 tsutsui } 1715 1.1 tsutsui } 1716 1.1 tsutsui 1717 1.1 tsutsui /* 1718 1.1 tsutsui * Note MEC chip seems to insert 2 byte padding at the top of 1719 1.1 tsutsui * RX buffer, but we copy whole buffer to avoid unaligned copy. 1720 1.1 tsutsui */ 1721 1.34 tsutsui MEC_RXBUFSYNC(sc, i, len + ETHER_CRC_LEN, BUS_DMASYNC_POSTREAD); 1722 1.10 christos memcpy(mtod(m, void *), rxd->rxd_buf, MEC_ETHER_ALIGN + len); 1723 1.34 tsutsui crc = be32dec(rxd->rxd_buf + MEC_ETHER_ALIGN + len); 1724 1.1 tsutsui MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); 1725 1.1 tsutsui m->m_data += MEC_ETHER_ALIGN; 1726 1.1 tsutsui 1727 1.1 tsutsui /* put RX buffer into FIFO again */ 1728 1.1 tsutsui rxd->rxd_stat = 0; 1729 1.1 tsutsui MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); 1730 1.1 tsutsui bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); 1731 1.1 tsutsui 1732 1.53 ozaki m_set_rcvif(m, ifp); 1733 1.1 tsutsui m->m_pkthdr.len = m->m_len = len; 1734 1.34 tsutsui if ((ifp->if_csum_flags_rx & (M_CSUM_TCPv4|M_CSUM_UDPv4)) != 0) 1735 1.34 tsutsui mec_rxcsum(sc, m, RXSTAT_CKSUM(rxstat), crc); 1736 1.1 tsutsui 1737 1.1 tsutsui /* Pass it on. */ 1738 1.52 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1739 1.1 tsutsui } 1740 1.1 tsutsui 1741 1.1 tsutsui /* update RX pointer */ 1742 1.1 tsutsui sc->sc_rxptr = i; 1743 1.1 tsutsui } 1744 1.1 tsutsui 1745 1.19 tsutsui static void 1746 1.34 tsutsui mec_rxcsum(struct mec_softc *sc, struct mbuf *m, uint16_t rxcsum, uint32_t crc) 1747 1.34 tsutsui { 1748 1.34 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1749 1.34 tsutsui struct ether_header *eh; 1750 1.34 tsutsui struct ip *ip; 1751 1.34 tsutsui struct udphdr *uh; 1752 1.34 tsutsui u_int len, pktlen, hlen; 1753 1.34 tsutsui uint32_t csum_data, dsum; 1754 1.34 tsutsui int csum_flags; 1755 1.34 tsutsui const uint16_t *dp; 1756 1.34 tsutsui 1757 1.34 tsutsui csum_data = 0; 1758 1.34 tsutsui csum_flags = 0; 1759 1.34 tsutsui 1760 1.34 tsutsui len = m->m_len; 1761 1.34 tsutsui if (len < ETHER_HDR_LEN + sizeof(struct ip)) 1762 1.34 tsutsui goto out; 1763 1.34 tsutsui pktlen = len - ETHER_HDR_LEN; 1764 1.34 tsutsui eh = mtod(m, struct ether_header *); 1765 1.34 tsutsui if (ntohs(eh->ether_type) != ETHERTYPE_IP) 1766 1.34 tsutsui goto out; 1767 1.34 tsutsui ip = (struct ip *)((uint8_t *)eh + ETHER_HDR_LEN); 1768 1.34 tsutsui if (ip->ip_v != IPVERSION) 1769 1.34 tsutsui goto out; 1770 1.34 tsutsui 1771 1.34 tsutsui hlen = ip->ip_hl << 2; 1772 1.34 tsutsui if (hlen < sizeof(struct ip)) 1773 1.34 tsutsui goto out; 1774 1.34 tsutsui 1775 1.34 tsutsui /* 1776 1.34 tsutsui * Bail if too short, has random trailing garbage, truncated, 1777 1.34 tsutsui * fragment, or has ethernet pad. 1778 1.34 tsutsui */ 1779 1.34 tsutsui if (ntohs(ip->ip_len) < hlen || 1780 1.34 tsutsui ntohs(ip->ip_len) != pktlen || 1781 1.34 tsutsui (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) != 0) 1782 1.34 tsutsui goto out; 1783 1.34 tsutsui 1784 1.34 tsutsui switch (ip->ip_p) { 1785 1.34 tsutsui case IPPROTO_TCP: 1786 1.34 tsutsui if ((ifp->if_csum_flags_rx & M_CSUM_TCPv4) == 0 || 1787 1.34 tsutsui pktlen < (hlen + sizeof(struct tcphdr))) 1788 1.34 tsutsui goto out; 1789 1.34 tsutsui csum_flags = M_CSUM_TCPv4 | M_CSUM_DATA | M_CSUM_NO_PSEUDOHDR; 1790 1.34 tsutsui break; 1791 1.34 tsutsui case IPPROTO_UDP: 1792 1.34 tsutsui if ((ifp->if_csum_flags_rx & M_CSUM_UDPv4) == 0 || 1793 1.34 tsutsui pktlen < (hlen + sizeof(struct udphdr))) 1794 1.34 tsutsui goto out; 1795 1.34 tsutsui uh = (struct udphdr *)((uint8_t *)ip + hlen); 1796 1.34 tsutsui if (uh->uh_sum == 0) 1797 1.34 tsutsui goto out; /* no checksum */ 1798 1.34 tsutsui csum_flags = M_CSUM_UDPv4 | M_CSUM_DATA | M_CSUM_NO_PSEUDOHDR; 1799 1.34 tsutsui break; 1800 1.34 tsutsui default: 1801 1.34 tsutsui goto out; 1802 1.34 tsutsui } 1803 1.34 tsutsui 1804 1.34 tsutsui /* 1805 1.34 tsutsui * The computed checksum includes Ethernet header, IP headers, 1806 1.34 tsutsui * and CRC, so we have to deduct them. 1807 1.34 tsutsui * Note IP header cksum should be 0xffff so we don't have to 1808 1.34 tsutsui * dedecut them. 1809 1.34 tsutsui */ 1810 1.34 tsutsui dsum = 0; 1811 1.34 tsutsui 1812 1.34 tsutsui /* deduct Ethernet header */ 1813 1.34 tsutsui dp = (const uint16_t *)eh; 1814 1.34 tsutsui for (hlen = 0; hlen < (ETHER_HDR_LEN / sizeof(uint16_t)); hlen++) 1815 1.34 tsutsui dsum += ntohs(*dp++); 1816 1.34 tsutsui 1817 1.34 tsutsui /* deduct CRC */ 1818 1.34 tsutsui if (len & 1) { 1819 1.34 tsutsui dsum += (crc >> 24) & 0x00ff; 1820 1.34 tsutsui dsum += (crc >> 8) & 0xffff; 1821 1.34 tsutsui dsum += (crc << 8) & 0xff00; 1822 1.34 tsutsui } else { 1823 1.34 tsutsui dsum += (crc >> 16) & 0xffff; 1824 1.34 tsutsui dsum += (crc >> 0) & 0xffff; 1825 1.34 tsutsui } 1826 1.34 tsutsui while (dsum >> 16) 1827 1.34 tsutsui dsum = (dsum >> 16) + (dsum & 0xffff); 1828 1.34 tsutsui 1829 1.34 tsutsui csum_data = rxcsum; 1830 1.34 tsutsui csum_data += (uint16_t)~dsum; 1831 1.34 tsutsui 1832 1.34 tsutsui while (csum_data >> 16) 1833 1.34 tsutsui csum_data = (csum_data >> 16) + (csum_data & 0xffff); 1834 1.34 tsutsui 1835 1.34 tsutsui out: 1836 1.34 tsutsui m->m_pkthdr.csum_flags = csum_flags; 1837 1.34 tsutsui m->m_pkthdr.csum_data = csum_data; 1838 1.34 tsutsui } 1839 1.34 tsutsui 1840 1.34 tsutsui static void 1841 1.21 tsutsui mec_txintr(struct mec_softc *sc, uint32_t txptr) 1842 1.1 tsutsui { 1843 1.1 tsutsui struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1844 1.1 tsutsui struct mec_txdesc *txd; 1845 1.1 tsutsui struct mec_txsoft *txs; 1846 1.1 tsutsui bus_dmamap_t dmamap; 1847 1.1 tsutsui uint64_t txstat; 1848 1.1 tsutsui int i; 1849 1.1 tsutsui u_int col; 1850 1.1 tsutsui 1851 1.35 tsutsui DPRINTF(MEC_DEBUG_TXINTR, ("%s: called\n", __func__)); 1852 1.1 tsutsui 1853 1.21 tsutsui for (i = sc->sc_txdirty; i != txptr && sc->sc_txpending != 0; 1854 1.1 tsutsui i = MEC_NEXTTX(i), sc->sc_txpending--) { 1855 1.1 tsutsui txd = &sc->sc_txdesc[i]; 1856 1.1 tsutsui 1857 1.31 tsutsui MEC_TXCMDSYNC(sc, i, 1858 1.59 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1859 1.1 tsutsui 1860 1.1 tsutsui txstat = txd->txd_stat; 1861 1.1 tsutsui DPRINTF(MEC_DEBUG_TXINTR, 1862 1.35 tsutsui ("%s: dirty = %d, txstat = 0x%016llx\n", 1863 1.35 tsutsui __func__, i, txstat)); 1864 1.1 tsutsui if ((txstat & MEC_TXSTAT_SENT) == 0) { 1865 1.1 tsutsui MEC_TXCMDSYNC(sc, i, BUS_DMASYNC_PREREAD); 1866 1.1 tsutsui break; 1867 1.1 tsutsui } 1868 1.1 tsutsui 1869 1.1 tsutsui txs = &sc->sc_txsoft[i]; 1870 1.31 tsutsui if ((txs->txs_flags & MEC_TXS_TXDPTR) != 0) { 1871 1.1 tsutsui dmamap = txs->txs_dmamap; 1872 1.1 tsutsui bus_dmamap_sync(sc->sc_dmat, dmamap, 0, 1873 1.1 tsutsui dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1874 1.1 tsutsui bus_dmamap_unload(sc->sc_dmat, dmamap); 1875 1.1 tsutsui m_freem(txs->txs_mbuf); 1876 1.1 tsutsui txs->txs_mbuf = NULL; 1877 1.1 tsutsui } 1878 1.1 tsutsui 1879 1.1 tsutsui col = (txstat & MEC_TXSTAT_COLCNT) >> MEC_TXSTAT_COLCNT_SHIFT; 1880 1.63 thorpej if (col) 1881 1.63 thorpej if_statadd(ifp, if_collisions, col); 1882 1.27 tsutsui 1883 1.27 tsutsui if ((txstat & MEC_TXSTAT_SUCCESS) == 0) { 1884 1.41 matt printf("%s: TX error: txstat = 0x%016"PRIx64"\n", 1885 1.27 tsutsui device_xname(sc->sc_dev), txstat); 1886 1.63 thorpej if_statinc(ifp, if_oerrors); 1887 1.27 tsutsui } else 1888 1.63 thorpej if_statinc(ifp, if_opackets); 1889 1.1 tsutsui } 1890 1.1 tsutsui 1891 1.1 tsutsui /* update the dirty TX buffer pointer */ 1892 1.1 tsutsui sc->sc_txdirty = i; 1893 1.1 tsutsui DPRINTF(MEC_DEBUG_INTR, 1894 1.35 tsutsui ("%s: sc_txdirty = %2d, sc_txpending = %2d\n", 1895 1.35 tsutsui __func__, sc->sc_txdirty, sc->sc_txpending)); 1896 1.1 tsutsui 1897 1.1 tsutsui /* cancel the watchdog timer if there are no pending TX packets */ 1898 1.1 tsutsui if (sc->sc_txpending == 0) 1899 1.1 tsutsui ifp->if_timer = 0; 1900 1.1 tsutsui } 1901 1.1 tsutsui 1902 1.36 tsutsui static bool 1903 1.36 tsutsui mec_shutdown(device_t self, int howto) 1904 1.1 tsutsui { 1905 1.36 tsutsui struct mec_softc *sc = device_private(self); 1906 1.1 tsutsui 1907 1.1 tsutsui mec_stop(&sc->sc_ethercom.ec_if, 1); 1908 1.17 tsutsui /* make sure to stop DMA etc. */ 1909 1.17 tsutsui mec_reset(sc); 1910 1.36 tsutsui 1911 1.36 tsutsui return true; 1912 1.1 tsutsui } 1913