1/*- 2 * Copyright (c) 2012-2014 Bjoern A. Zeeb 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 7 * ("MRC2"), as part of the DARPA MRC research programme. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * This driver is modelled after atse(4). We need to seriously reduce the 31 * per-driver code we have to write^wcopy & paste. 32 * 33 * TODO: 34 * - figure out on the HW side why some data is LE and some is BE. 35 * - general set of improvements possible (e.g., reduce times of copying, 36 * do on-the-copy checksum calculations) 37 */ 38 39#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2012-2014 Bjoern A. Zeeb 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 7 * ("MRC2"), as part of the DARPA MRC research programme. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * This driver is modelled after atse(4). We need to seriously reduce the 31 * per-driver code we have to write^wcopy & paste. 32 * 33 * TODO: 34 * - figure out on the HW side why some data is LE and some is BE. 35 * - general set of improvements possible (e.g., reduce times of copying, 36 * do on-the-copy checksum calculations) 37 */ 38 39#include <sys/cdefs.h>
|
40__FBSDID("$FreeBSD: head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c 267919 2014-06-26 17:03:08Z bz $");
| 40__FBSDID("$FreeBSD: head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c 267920 2014-06-26 17:10:07Z bz $");
|
41 42#include "opt_device_polling.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/bus.h> 48#include <sys/endian.h> 49#include <sys/lock.h> 50#include <sys/module.h> 51#include <sys/mutex.h> 52#include <sys/proc.h> 53#include <sys/socket.h> 54#include <sys/sockio.h> 55#include <sys/types.h> 56 57#include <net/ethernet.h> 58#include <net/if.h> 59#include <net/if_var.h> 60#include <net/if_dl.h> 61#include <net/if_media.h> 62#include <net/if_types.h> 63#include <net/if_vlan_var.h> 64 65#include <net/bpf.h> 66 67#include <machine/bus.h> 68#include <machine/resource.h> 69#include <sys/rman.h> 70 71#include "if_nf10bmacreg.h" 72 73#ifndef NF10BMAC_MAX_PKTS 74/* 75 * We have a 4k buffer in HW, so do not try to send more than 3 packets. 76 * At the time of writing HW is orders of magnitude faster than we can 77 * enqueue so it would not matter but need an escape. 78 */ 79#define NF10BMAC_MAX_PKTS 3 80#endif 81 82#ifndef NF10BMAC_WATCHDOG_TIME 83#define NF10BMAC_WATCHDOG_TIME 5 /* seconds */ 84#endif 85 86#ifdef DEVICE_POLLING 87static poll_handler_t nf10bmac_poll; 88#endif 89 90#define NF10BMAC_LOCK(_sc) mtx_lock(&(_sc)->nf10bmac_mtx) 91#define NF10BMAC_UNLOCK(_sc) mtx_unlock(&(_sc)->nf10bmac_mtx) 92#define NF10BMAC_LOCK_ASSERT(_sc) \ 93 mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED) 94 95#define NF10BMAC_CTRL0 0x00 96#define NF10BMAC_TX_DATA 0x00 97#define NF10BMAC_TX_META 0x08 98#define NF10BMAC_TX_LEN 0x10 99#define NF10BMAC_RX_DATA 0x00 100#define NF10BMAC_RX_META 0x08 101#define NF10BMAC_RX_LEN 0x10 102#define NF10BMAC_INTR_CLEAR_DIS 0x00 103#define NF10BMAC_INTR_CTRL 0x08 104 105#define NF10BMAC_TUSER_MAC0 (1 << 0) 106#define NF10BMAC_TUSER_CPU0 (1 << 1) 107#define NF10BMAC_TUSER_MAC1 (1 << 2) 108#define NF10BMAC_TUSER_CPU1 (1 << 3) 109#define NF10BMAC_TUSER_MAC2 (1 << 4) 110#define NF10BMAC_TUSER_CPU2 (1 << 5) 111#define NF10BMAC_TUSER_MAC3 (1 << 6) 112#define NF10BMAC_TUSER_CPU3 (1 << 7) 113 114#define NF10BMAC_DATA_LEN_MASK 0x0000ffff 115#define NF10BMAC_DATA_DPORT_MASK 0xff000000 116#define NF10BMAC_DATA_DPORT_SHIFT 24 117#define NF10BMAC_DATA_SPORT_MASK 0x00ff0000 118#define NF10BMAC_DATA_SPORT_SHIFT 16 119#define NF10BMAC_DATA_LAST 0x00008000
| 41 42#include "opt_device_polling.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/bus.h> 48#include <sys/endian.h> 49#include <sys/lock.h> 50#include <sys/module.h> 51#include <sys/mutex.h> 52#include <sys/proc.h> 53#include <sys/socket.h> 54#include <sys/sockio.h> 55#include <sys/types.h> 56 57#include <net/ethernet.h> 58#include <net/if.h> 59#include <net/if_var.h> 60#include <net/if_dl.h> 61#include <net/if_media.h> 62#include <net/if_types.h> 63#include <net/if_vlan_var.h> 64 65#include <net/bpf.h> 66 67#include <machine/bus.h> 68#include <machine/resource.h> 69#include <sys/rman.h> 70 71#include "if_nf10bmacreg.h" 72 73#ifndef NF10BMAC_MAX_PKTS 74/* 75 * We have a 4k buffer in HW, so do not try to send more than 3 packets. 76 * At the time of writing HW is orders of magnitude faster than we can 77 * enqueue so it would not matter but need an escape. 78 */ 79#define NF10BMAC_MAX_PKTS 3 80#endif 81 82#ifndef NF10BMAC_WATCHDOG_TIME 83#define NF10BMAC_WATCHDOG_TIME 5 /* seconds */ 84#endif 85 86#ifdef DEVICE_POLLING 87static poll_handler_t nf10bmac_poll; 88#endif 89 90#define NF10BMAC_LOCK(_sc) mtx_lock(&(_sc)->nf10bmac_mtx) 91#define NF10BMAC_UNLOCK(_sc) mtx_unlock(&(_sc)->nf10bmac_mtx) 92#define NF10BMAC_LOCK_ASSERT(_sc) \ 93 mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED) 94 95#define NF10BMAC_CTRL0 0x00 96#define NF10BMAC_TX_DATA 0x00 97#define NF10BMAC_TX_META 0x08 98#define NF10BMAC_TX_LEN 0x10 99#define NF10BMAC_RX_DATA 0x00 100#define NF10BMAC_RX_META 0x08 101#define NF10BMAC_RX_LEN 0x10 102#define NF10BMAC_INTR_CLEAR_DIS 0x00 103#define NF10BMAC_INTR_CTRL 0x08 104 105#define NF10BMAC_TUSER_MAC0 (1 << 0) 106#define NF10BMAC_TUSER_CPU0 (1 << 1) 107#define NF10BMAC_TUSER_MAC1 (1 << 2) 108#define NF10BMAC_TUSER_CPU1 (1 << 3) 109#define NF10BMAC_TUSER_MAC2 (1 << 4) 110#define NF10BMAC_TUSER_CPU2 (1 << 5) 111#define NF10BMAC_TUSER_MAC3 (1 << 6) 112#define NF10BMAC_TUSER_CPU3 (1 << 7) 113 114#define NF10BMAC_DATA_LEN_MASK 0x0000ffff 115#define NF10BMAC_DATA_DPORT_MASK 0xff000000 116#define NF10BMAC_DATA_DPORT_SHIFT 24 117#define NF10BMAC_DATA_SPORT_MASK 0x00ff0000 118#define NF10BMAC_DATA_SPORT_SHIFT 16 119#define NF10BMAC_DATA_LAST 0x00008000
|
| 120#ifdef NF10BMAC_64BIT 121#define NF10BMAC_DATA_STRB 0x000000ff 122#define REGWTYPE uint64_t 123#else
|
120#define NF10BMAC_DATA_STRB 0x0000000f
| 124#define NF10BMAC_DATA_STRB 0x0000000f
|
| 125#define REGWTYPE uint32_t 126#endif
|
121 122 123static inline void
| 127 128 129static inline void
|
124nf10bmac_write(struct resource *res, uint32_t reg, uint32_t val,
| 130nf10bmac_write(struct resource *res, REGWTYPE reg, REGWTYPE val,
|
125 const char *f __unused, const int l __unused) 126{ 127
| 131 const char *f __unused, const int l __unused) 132{ 133
|
| 134#ifdef NF10BMAC_64BIT 135 bus_write_8(res, reg, htole64(val)); 136#else
|
128 bus_write_4(res, reg, htole32(val));
| 137 bus_write_4(res, reg, htole32(val));
|
| 138#endif
|
129} 130
| 139} 140
|
131static inline uint32_t 132nf10bmac_read(struct resource *res, uint32_t reg,
| 141static inline REGWTYPE 142nf10bmac_read(struct resource *res, REGWTYPE reg,
|
133 const char *f __unused, const int l __unused) 134{ 135
| 143 const char *f __unused, const int l __unused) 144{ 145
|
| 146#ifdef NF10BMAC_64BIT 147 return (le64toh(bus_read_8(res, reg))); 148#else
|
136 return (le32toh(bus_read_4(res, reg)));
| 149 return (le32toh(bus_read_4(res, reg)));
|
| 150#endif
|
137} 138 139static inline void
| 151} 152 153static inline void
|
140nf10bmac_write_be(struct resource *res, uint32_t reg, uint32_t val,
| 154nf10bmac_write_be(struct resource *res, REGWTYPE reg, REGWTYPE val,
|
141 const char *f __unused, const int l __unused) 142{ 143
| 155 const char *f __unused, const int l __unused) 156{ 157
|
| 158#ifdef NF10BMAC_64BIT 159 bus_write_8(res, reg, htobe64(val)); 160#else
|
144 bus_write_4(res, reg, htobe32(val));
| 161 bus_write_4(res, reg, htobe32(val));
|
| 162#endif
|
145} 146 147
| 163} 164 165
|
148static inline uint32_t 149nf10bmac_read_be(struct resource *res, uint32_t reg,
| 166static inline REGWTYPE 167nf10bmac_read_be(struct resource *res, REGWTYPE reg,
|
150 const char *f __unused, const int l __unused) 151{ 152
| 168 const char *f __unused, const int l __unused) 169{ 170
|
| 171#ifdef NF10BMAC_64BIT 172 return (be64toh(bus_read_8(res, reg))); 173#else
|
153 return (be32toh(bus_read_4(res, reg)));
| 174 return (be32toh(bus_read_4(res, reg)));
|
| 175#endif
|
154} 155 156#define NF10BMAC_WRITE_CTRL(sc, reg, val) \ 157 nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val), \ 158 __func__, __LINE__) 159#define NF10BMAC_WRITE(sc, reg, val) \ 160 nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val), \ 161 __func__, __LINE__) 162#define NF10BMAC_READ(sc, reg) \ 163 nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg), \ 164 __func__, __LINE__) 165#define NF10BMAC_WRITE_BE(sc, reg, val) \ 166 nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val), \ 167 __func__, __LINE__) 168#define NF10BMAC_READ_BE(sc, reg) \ 169 nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg), \ 170 __func__, __LINE__) 171 172#define NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l) \ 173 nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val), \ 174 (_f), (_l)) 175 176#define NF10BMAC_RX_INTR_CLEAR_DIS(sc) \ 177 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1, \ 178 __func__, __LINE__) 179#define NF10BMAC_RX_INTR_ENABLE(sc) \ 180 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1, \ 181 __func__, __LINE__) 182#define NF10BMAC_RX_INTR_DISABLE(sc) \ 183 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0, \ 184 __func__, __LINE__) 185 186 187#ifdef ENABLE_WATCHDOG 188static void nf10bmac_tick(void *); 189#endif 190static int nf10bmac_detach(device_t); 191 192devclass_t nf10bmac_devclass; 193 194 195static int 196nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m) 197{ 198 int32_t len, l, ml;
| 176} 177 178#define NF10BMAC_WRITE_CTRL(sc, reg, val) \ 179 nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val), \ 180 __func__, __LINE__) 181#define NF10BMAC_WRITE(sc, reg, val) \ 182 nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val), \ 183 __func__, __LINE__) 184#define NF10BMAC_READ(sc, reg) \ 185 nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg), \ 186 __func__, __LINE__) 187#define NF10BMAC_WRITE_BE(sc, reg, val) \ 188 nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val), \ 189 __func__, __LINE__) 190#define NF10BMAC_READ_BE(sc, reg) \ 191 nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg), \ 192 __func__, __LINE__) 193 194#define NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l) \ 195 nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val), \ 196 (_f), (_l)) 197 198#define NF10BMAC_RX_INTR_CLEAR_DIS(sc) \ 199 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1, \ 200 __func__, __LINE__) 201#define NF10BMAC_RX_INTR_ENABLE(sc) \ 202 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1, \ 203 __func__, __LINE__) 204#define NF10BMAC_RX_INTR_DISABLE(sc) \ 205 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0, \ 206 __func__, __LINE__) 207 208 209#ifdef ENABLE_WATCHDOG 210static void nf10bmac_tick(void *); 211#endif 212static int nf10bmac_detach(device_t); 213 214devclass_t nf10bmac_devclass; 215 216 217static int 218nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m) 219{ 220 int32_t len, l, ml;
|
199 uint32_t md, val;
| 221 REGWTYPE md, val;
|
200 201 NF10BMAC_LOCK_ASSERT(sc); 202 203 KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc)); 204 KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m)); 205 /* 206 * Copy to buffer to minimize our pain as we can only store 207 * double words which, after the first mbuf gets out of alignment 208 * quite quickly. 209 */ 210 m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf); 211 len = m->m_pkthdr.len; 212 213 /* Write the length at start of packet. */ 214 NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len); 215 216 /* Write the meta data and data. */ 217 ml = len / sizeof(val); 218 len -= (ml * sizeof(val)); 219 for (l = 0; l <= ml; l++) { 220 int32_t cl; 221 222 cl = sizeof(val); 223 md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT); 224 if (l == ml || (len == 0 && l == (ml - 1))) { 225 if (l == ml && len == 0) { 226 break; 227 } else { 228 uint8_t s; 229 int sl; 230 231 if (l == (ml - 1)) 232 len = sizeof(val); 233 cl = len; 234 235 for (s = 0, sl = len; sl > 0; sl--) 236 s |= (1 << (sl - 1)); 237 md |= (s & NF10BMAC_DATA_STRB); 238 md |= NF10BMAC_DATA_LAST; 239 } 240 } else { 241 md |= NF10BMAC_DATA_STRB; 242 } 243 NF10BMAC_WRITE(sc, NF10BMAC_TX_META, md); 244 bcopy(&sc->nf10bmac_tx_buf[l*sizeof(val)], &val, cl); 245 NF10BMAC_WRITE_BE(sc, NF10BMAC_TX_DATA, val); 246 } 247 248 /* If anyone is interested give them a copy. */ 249 BPF_MTAP(sc->nf10bmac_ifp, m); 250 251 m_freem(m); 252 253 return (0); 254} 255 256static void 257nf10bmac_start_locked(struct ifnet *ifp) 258{ 259 struct nf10bmac_softc *sc; 260 int count, error; 261 262 sc = ifp->if_softc; 263 NF10BMAC_LOCK_ASSERT(sc); 264 265 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 266 IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0) 267 return; 268 269#ifdef ENABLE_WATCHDOG 270 /* 271 * Disable the watchdog while sending, we are batching packets. 272 * Though we should never reach 5 seconds, and are holding the lock, 273 * but who knows. 274 */ 275 sc->nf10bmac_watchdog_timer = 0; 276#endif 277 278 /* Send up to MAX_PKTS_PER_TX_LOOP packets. */ 279 for (count = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && 280 count < NF10BMAC_MAX_PKTS; count++) { 281 struct mbuf *m; 282 283 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 284 if (m == NULL) 285 break; 286 error = nf10bmac_tx_locked(sc, m); 287 if (error != 0) 288 break; 289 } 290 291#ifdef ENABLE_WATCHDOG 292done: 293 /* If the IP core walks into Nekromanteion try to bail out. */ 294 /* XXX-BZ useless until we have direct FIFO fill status feedback. */ 295 if (count > 0) 296 sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME; 297#endif 298} 299 300static void 301nf10bmac_start(struct ifnet *ifp) 302{ 303 struct nf10bmac_softc *sc; 304 305 sc = ifp->if_softc; 306 NF10BMAC_LOCK(sc); 307 nf10bmac_start_locked(ifp); 308 NF10BMAC_UNLOCK(sc); 309} 310 311static void 312nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc) 313{
| 222 223 NF10BMAC_LOCK_ASSERT(sc); 224 225 KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc)); 226 KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m)); 227 /* 228 * Copy to buffer to minimize our pain as we can only store 229 * double words which, after the first mbuf gets out of alignment 230 * quite quickly. 231 */ 232 m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf); 233 len = m->m_pkthdr.len; 234 235 /* Write the length at start of packet. */ 236 NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len); 237 238 /* Write the meta data and data. */ 239 ml = len / sizeof(val); 240 len -= (ml * sizeof(val)); 241 for (l = 0; l <= ml; l++) { 242 int32_t cl; 243 244 cl = sizeof(val); 245 md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT); 246 if (l == ml || (len == 0 && l == (ml - 1))) { 247 if (l == ml && len == 0) { 248 break; 249 } else { 250 uint8_t s; 251 int sl; 252 253 if (l == (ml - 1)) 254 len = sizeof(val); 255 cl = len; 256 257 for (s = 0, sl = len; sl > 0; sl--) 258 s |= (1 << (sl - 1)); 259 md |= (s & NF10BMAC_DATA_STRB); 260 md |= NF10BMAC_DATA_LAST; 261 } 262 } else { 263 md |= NF10BMAC_DATA_STRB; 264 } 265 NF10BMAC_WRITE(sc, NF10BMAC_TX_META, md); 266 bcopy(&sc->nf10bmac_tx_buf[l*sizeof(val)], &val, cl); 267 NF10BMAC_WRITE_BE(sc, NF10BMAC_TX_DATA, val); 268 } 269 270 /* If anyone is interested give them a copy. */ 271 BPF_MTAP(sc->nf10bmac_ifp, m); 272 273 m_freem(m); 274 275 return (0); 276} 277 278static void 279nf10bmac_start_locked(struct ifnet *ifp) 280{ 281 struct nf10bmac_softc *sc; 282 int count, error; 283 284 sc = ifp->if_softc; 285 NF10BMAC_LOCK_ASSERT(sc); 286 287 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 288 IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0) 289 return; 290 291#ifdef ENABLE_WATCHDOG 292 /* 293 * Disable the watchdog while sending, we are batching packets. 294 * Though we should never reach 5 seconds, and are holding the lock, 295 * but who knows. 296 */ 297 sc->nf10bmac_watchdog_timer = 0; 298#endif 299 300 /* Send up to MAX_PKTS_PER_TX_LOOP packets. */ 301 for (count = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && 302 count < NF10BMAC_MAX_PKTS; count++) { 303 struct mbuf *m; 304 305 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 306 if (m == NULL) 307 break; 308 error = nf10bmac_tx_locked(sc, m); 309 if (error != 0) 310 break; 311 } 312 313#ifdef ENABLE_WATCHDOG 314done: 315 /* If the IP core walks into Nekromanteion try to bail out. */ 316 /* XXX-BZ useless until we have direct FIFO fill status feedback. */ 317 if (count > 0) 318 sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME; 319#endif 320} 321 322static void 323nf10bmac_start(struct ifnet *ifp) 324{ 325 struct nf10bmac_softc *sc; 326 327 sc = ifp->if_softc; 328 NF10BMAC_LOCK(sc); 329 nf10bmac_start_locked(ifp); 330 NF10BMAC_UNLOCK(sc); 331} 332 333static void 334nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc) 335{
|
314 uint32_t md, val;
| 336 REGWTYPE md, val;
|
315 316 do { 317 md = NF10BMAC_READ_BE(sc, NF10BMAC_RX_META); 318 if ((md & NF10BMAC_DATA_STRB) != 0) 319 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA); 320 } while ((md & NF10BMAC_DATA_STRB) != 0 && 321 (md & NF10BMAC_DATA_LAST) == 0); 322} 323 324static int 325nf10bmac_rx_locked(struct nf10bmac_softc *sc) 326{ 327 struct ifnet *ifp; 328 struct mbuf *m;
| 337 338 do { 339 md = NF10BMAC_READ_BE(sc, NF10BMAC_RX_META); 340 if ((md & NF10BMAC_DATA_STRB) != 0) 341 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA); 342 } while ((md & NF10BMAC_DATA_STRB) != 0 && 343 (md & NF10BMAC_DATA_LAST) == 0); 344} 345 346static int 347nf10bmac_rx_locked(struct nf10bmac_softc *sc) 348{ 349 struct ifnet *ifp; 350 struct mbuf *m;
|
329 uint32_t md, val;
| 351 REGWTYPE md, val;
|
330 int32_t len, l; 331 332 /* 333 * General problem here in case we need to sync ourselves to the 334 * beginning of a packet. Length will only be set for the first 335 * read, and together with strb we can detect the begining (or 336 * skip to tlast). 337 */ 338 339 len = NF10BMAC_READ(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK; 340 if (len > (MCLBYTES - ETHER_ALIGN)) { 341 nf10bmac_eat_packet_munch_munch(sc); 342 return (0); 343 } 344 345 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 346 if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) { 347 /* No packet data available. */ 348 return (0); 349 } else if (len == 0 && (md & NF10BMAC_DATA_STRB) != 0) { 350 /* We are in the middle of a packet. */ 351 nf10bmac_eat_packet_munch_munch(sc); 352 return (0); 353 } else if ((md & NF10BMAC_DATA_STRB) == 0) { 354 /* Invalid length "hint". */ 355 device_printf(sc->nf10bmac_dev, 356 "Unexpected length %d on zero strb\n", len); 357 return (0); 358 } 359 360 /* Assume at this point that we have data and a full packet. */ 361 if ((len + ETHER_ALIGN) >= MINCLSIZE) { 362 /* Get a cluster. */ 363 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 364 if (m == NULL) 365 return (0); 366 m->m_len = m->m_pkthdr.len = MCLBYTES; 367 } else { 368 /* Hey this still fits into the mbuf+pkthdr. */ 369 m = m_gethdr(M_NOWAIT, MT_DATA); 370 if (m == NULL) 371 return (0); 372 m->m_len = m->m_pkthdr.len = MHLEN; 373 } 374 /* Make sure upper layers will be aligned. */ 375 m_adj(m, ETHER_ALIGN); 376 377 ifp = sc->nf10bmac_ifp; 378 l = 0; 379/* 380 while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) { 381*/ 382 while (l < len) { 383 size_t cl; 384 385 if ((md & NF10BMAC_DATA_LAST) == 0 && 386 (len - l) < sizeof(val)) { 387 /* 388 * Our length and LAST disagree. We have a valid STRB. 389 * We could continue until we fill the mbuf and just 390 * log the invlid length "hint". For now drop the 391 * packet on the floor and count the error. 392 */ 393 nf10bmac_eat_packet_munch_munch(sc); 394 ifp->if_ierrors++; 395 m_freem(m); 396 return (0); 397 } else if ((len - l) <= sizeof(val)) { 398 cl = len - l; 399 } else { 400 cl = sizeof(val); 401 } 402 403 /* Read the first bytes of data as well. */ 404 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA); 405 bcopy(&val, (uint8_t *)(m->m_data + l), cl); 406 l += cl; 407 408 if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len) 409 break; 410 else { 411 DELAY(50); 412 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 413 } 414 415 cl = 10; 416 while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) { 417 DELAY(10); 418 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 419 } 420 } 421 /* We should get out of this loop with tlast and tsrb. */ 422 if ((md & NF10BMAC_DATA_LAST) == 0 || (md & NF10BMAC_DATA_STRB) == 0) { 423 device_printf(sc->nf10bmac_dev, "Unexpected rx loop end state: "
| 352 int32_t len, l; 353 354 /* 355 * General problem here in case we need to sync ourselves to the 356 * beginning of a packet. Length will only be set for the first 357 * read, and together with strb we can detect the begining (or 358 * skip to tlast). 359 */ 360 361 len = NF10BMAC_READ(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK; 362 if (len > (MCLBYTES - ETHER_ALIGN)) { 363 nf10bmac_eat_packet_munch_munch(sc); 364 return (0); 365 } 366 367 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 368 if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) { 369 /* No packet data available. */ 370 return (0); 371 } else if (len == 0 && (md & NF10BMAC_DATA_STRB) != 0) { 372 /* We are in the middle of a packet. */ 373 nf10bmac_eat_packet_munch_munch(sc); 374 return (0); 375 } else if ((md & NF10BMAC_DATA_STRB) == 0) { 376 /* Invalid length "hint". */ 377 device_printf(sc->nf10bmac_dev, 378 "Unexpected length %d on zero strb\n", len); 379 return (0); 380 } 381 382 /* Assume at this point that we have data and a full packet. */ 383 if ((len + ETHER_ALIGN) >= MINCLSIZE) { 384 /* Get a cluster. */ 385 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 386 if (m == NULL) 387 return (0); 388 m->m_len = m->m_pkthdr.len = MCLBYTES; 389 } else { 390 /* Hey this still fits into the mbuf+pkthdr. */ 391 m = m_gethdr(M_NOWAIT, MT_DATA); 392 if (m == NULL) 393 return (0); 394 m->m_len = m->m_pkthdr.len = MHLEN; 395 } 396 /* Make sure upper layers will be aligned. */ 397 m_adj(m, ETHER_ALIGN); 398 399 ifp = sc->nf10bmac_ifp; 400 l = 0; 401/* 402 while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) { 403*/ 404 while (l < len) { 405 size_t cl; 406 407 if ((md & NF10BMAC_DATA_LAST) == 0 && 408 (len - l) < sizeof(val)) { 409 /* 410 * Our length and LAST disagree. We have a valid STRB. 411 * We could continue until we fill the mbuf and just 412 * log the invlid length "hint". For now drop the 413 * packet on the floor and count the error. 414 */ 415 nf10bmac_eat_packet_munch_munch(sc); 416 ifp->if_ierrors++; 417 m_freem(m); 418 return (0); 419 } else if ((len - l) <= sizeof(val)) { 420 cl = len - l; 421 } else { 422 cl = sizeof(val); 423 } 424 425 /* Read the first bytes of data as well. */ 426 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA); 427 bcopy(&val, (uint8_t *)(m->m_data + l), cl); 428 l += cl; 429 430 if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len) 431 break; 432 else { 433 DELAY(50); 434 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 435 } 436 437 cl = 10; 438 while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) { 439 DELAY(10); 440 md = NF10BMAC_READ(sc, NF10BMAC_RX_META); 441 } 442 } 443 /* We should get out of this loop with tlast and tsrb. */ 444 if ((md & NF10BMAC_DATA_LAST) == 0 || (md & NF10BMAC_DATA_STRB) == 0) { 445 device_printf(sc->nf10bmac_dev, "Unexpected rx loop end state: "
|
424 "md=0x%08x len=%d l=%d\n", md, len, l);
| 446 "md=0x%08jx len=%d l=%d\n", (uintmax_t)md, len, l);
|
425 ifp->if_ierrors++; 426 m_freem(m); 427 return (0); 428 } 429 430 m->m_pkthdr.len = m->m_len = len; 431 m->m_pkthdr.rcvif = ifp; 432 ifp->if_ipackets++; 433 434 NF10BMAC_UNLOCK(sc); 435 (*ifp->if_input)(ifp, m); 436 NF10BMAC_LOCK(sc); 437 438 return (1); 439} 440 441 442static int 443nf10bmac_stop_locked(struct nf10bmac_softc *sc) 444{ 445 struct ifnet *ifp; 446 447 NF10BMAC_LOCK_ASSERT(sc); 448 449#ifdef ENABLE_WATCHDOG 450 sc->nf10bmac_watchdog_timer = 0; 451 callout_stop(&sc->nf10bmac_tick); 452#endif 453 454 ifp = sc->nf10bmac_ifp; 455 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 456 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 457 458 sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK; 459 if_link_state_change(ifp, LINK_STATE_DOWN); 460 461 return (0); 462} 463 464static int 465nf10bmac_reset(struct nf10bmac_softc *sc) 466{ 467 468 /* 469 * If we do not have an ether address set, initialize to the same 470 * OUI as NetFPGA-10G Linux driver does (which luckily seems 471 * unallocated). We just change the NIC specific part from 472 * the slightly long "\0NF10C0" to "\0NFBSD". 473 * Oh and we keep the way of setting it from a string as they do. 474 * It's an amazing way to hide it. 475 * XXX-BZ If NetFPGA gets their own OUI we should fix this. 476 */ 477 if (sc->nf10bmac_eth_addr[0] == 0x00 && 478 sc->nf10bmac_eth_addr[1] == 0x00 && 479 sc->nf10bmac_eth_addr[2] == 0x00 && 480 sc->nf10bmac_eth_addr[3] == 0x00 && 481 sc->nf10bmac_eth_addr[4] == 0x00 && 482 sc->nf10bmac_eth_addr[5] == 0x00) { 483 memcpy(&sc->nf10bmac_eth_addr, "\0NFBSD", ETHER_ADDR_LEN); 484 sc->nf10bmac_eth_addr[5] += sc->nf10bmac_unit; 485 } 486 487 return (0); 488} 489 490static void 491nf10bmac_init_locked(struct nf10bmac_softc *sc) 492{ 493 struct ifnet *ifp; 494 uint8_t *eaddr; 495 496 NF10BMAC_LOCK_ASSERT(sc); 497 ifp = sc->nf10bmac_ifp; 498 499 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 500 return; 501 502 /* 503 * Must update the ether address if changed. Given we do not handle 504 * in nf10bmac_ioctl() but it's in the general framework, just always 505 * do it here before nf10bmac_reset(). 506 */ 507 eaddr = IF_LLADDR(sc->nf10bmac_ifp); 508 bcopy(eaddr, &sc->nf10bmac_eth_addr, ETHER_ADDR_LEN); 509 /* XXX-BZ we do not have any way to tell the NIC our ether address. */ 510 511 /* Make things frind to halt, cleanup, ... */ 512 nf10bmac_stop_locked(sc); 513 /* ... reset, ... */ 514 nf10bmac_reset(sc); 515 516 /* Memory rings? DMA engine? MC filter? MII? */ 517 /* Instead drain the FIFO; or at least a possible first packet.. */ 518 nf10bmac_eat_packet_munch_munch(sc); 519 520#ifdef DEVICE_POLLING 521 /* Only enable interrupts if we are not polling. */ 522 if (ifp->if_capenable & IFCAP_POLLING) { 523 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 524 } else 525#endif 526 { 527 NF10BMAC_RX_INTR_ENABLE(sc); 528 } 529 530 ifp->if_drv_flags |= IFF_DRV_RUNNING; 531 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 532 533 /* We have no underlying media, fake link state. */ 534 sc->nf10bmac_flags = NF10BMAC_FLAGS_LINK; /* Always up. */ 535 if_link_state_change(sc->nf10bmac_ifp, LINK_STATE_UP); 536 537#ifdef ENABLE_WATCHDOG 538 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc); 539#endif 540} 541 542static void 543nf10bmac_init(void *xsc) 544{ 545 struct nf10bmac_softc *sc; 546 547 sc = (struct nf10bmac_softc *)xsc; 548 NF10BMAC_LOCK(sc); 549 nf10bmac_init_locked(sc); 550 NF10BMAC_UNLOCK(sc); 551} 552 553#ifdef ENABLE_WATCHDOG 554static void 555nf10bmac_watchdog(struct nf10bmac_softc *sc) 556{ 557 558 NF10BMAC_LOCK_ASSERT(sc); 559 560 if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0) 561 return; 562 563 device_printf(sc->nf10bmac_dev, "watchdog timeout\n"); 564 sc->nf10bmac_ifp->if_oerrors++; 565 566 sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 567 nf10bmac_init_locked(sc); 568 569 if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd)) 570 nf10bmac_start_locked(sc->nf10bmac_ifp); 571} 572 573static void 574nf10bmac_tick(void *xsc) 575{ 576 struct nf10bmac_softc *sc; 577 struct ifnet *ifp; 578 579 sc = (struct nf10bmac_softc *)xsc; 580 NF10BMAC_LOCK_ASSERT(sc); 581 ifp = sc->nf10bmac_ifp; 582 583 nf10bmac_watchdog(sc); 584 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc); 585} 586#endif 587 588static void 589nf10bmac_intr(void *arg) 590{ 591 struct nf10bmac_softc *sc; 592 struct ifnet *ifp; 593 int rx_npkts; 594 595 sc = (struct nf10bmac_softc *)arg; 596 ifp = sc->nf10bmac_ifp; 597 598 NF10BMAC_LOCK(sc); 599#ifdef DEVICE_POLLING 600 if (ifp->if_capenable & IFCAP_POLLING) { 601 NF10BMAC_UNLOCK(sc); 602 return; 603 } 604#endif 605 606 /* NF10BMAC_RX_INTR_DISABLE(sc); */ 607 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 608 609 /* We only have an RX interrupt and no status information. */ 610 rx_npkts = 0; 611 while (rx_npkts < NF10BMAC_MAX_PKTS) { 612 int c; 613 614 c = nf10bmac_rx_locked(sc); 615 rx_npkts += c; 616 if (c == 0) 617 break; 618 } 619 620 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 621 /* Re-enable interrupts. */ 622 NF10BMAC_RX_INTR_ENABLE(sc); 623 624 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 625 nf10bmac_start_locked(ifp); 626 } 627 NF10BMAC_UNLOCK(sc); 628} 629 630 631#ifdef DEVICE_POLLING 632static int 633nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 634{ 635 struct nf10bmac_softc *sc; 636 int rx_npkts = 0; 637 638 sc = ifp->if_softc; 639 NF10BMAC_LOCK(sc); 640 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 641 NF10BMAC_UNLOCK(sc); 642 return (rx_npkts); 643 } 644 645 while (rx_npkts < count) { 646 int c; 647 648 c = nf10bmac_rx_locked(sc); 649 rx_npkts += c; 650 if (c == 0) 651 break; 652 } 653 nf10bmac_start_locked(ifp); 654 655 if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) { 656 /* We currently cannot do much. */ 657 ; 658 } 659 660 NF10BMAC_UNLOCK(sc); 661 return (rx_npkts); 662} 663#else 664#error We only support polling mode 665#endif /* DEVICE_POLLING */ 666 667static int 668nf10bmac_media_change(struct ifnet *ifp __unused) 669{ 670 671 /* Do nothing. */ 672 return (0); 673} 674 675static void 676nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr) 677{ 678 679 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 680 imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX; 681} 682 683static int 684nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 685{ 686 struct nf10bmac_softc *sc; 687 struct ifreq *ifr; 688 int error, mask; 689 690 error = 0; 691 sc = ifp->if_softc; 692 ifr = (struct ifreq *)data; 693 694 switch (command) { 695 case SIOCSIFFLAGS: 696 NF10BMAC_LOCK(sc); 697 if (ifp->if_flags & IFF_UP) { 698 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 699 ((ifp->if_flags ^ sc->nf10bmac_if_flags) & 700 (IFF_PROMISC | IFF_ALLMULTI)) != 0) 701 /* Nothing we can do. */ ; 702 else 703 nf10bmac_init_locked(sc); 704 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 705 nf10bmac_stop_locked(sc); 706 sc->nf10bmac_if_flags = ifp->if_flags; 707 NF10BMAC_UNLOCK(sc); 708 break; 709 case SIOCSIFCAP: 710 NF10BMAC_LOCK(sc); 711 mask = ifr->ifr_reqcap ^ ifp->if_capenable; 712#ifdef DEVICE_POLLING 713 if ((mask & IFCAP_POLLING) != 0 && 714 (IFCAP_POLLING & ifp->if_capabilities) != 0) { 715 ifp->if_capenable ^= IFCAP_POLLING; 716 if ((IFCAP_POLLING & ifp->if_capenable) != 0) { 717 718 error = ether_poll_register(nf10bmac_poll, ifp); 719 if (error != 0) { 720 NF10BMAC_UNLOCK(sc); 721 break; 722 } 723 724 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 725 726 /* 727 * Do not allow disabling of polling if we do 728 * not have interrupts. 729 */ 730 } else if (sc->nf10bmac_rx_irq_res != NULL) { 731 error = ether_poll_deregister(ifp); 732 /* Enable interrupts. */ 733 NF10BMAC_RX_INTR_ENABLE(sc); 734 } else { 735 ifp->if_capenable ^= IFCAP_POLLING; 736 error = EINVAL; 737 } 738 } 739#endif /* DEVICE_POLLING */ 740 NF10BMAC_UNLOCK(sc); 741 break; 742 case SIOCGIFMEDIA: 743 case SIOCSIFMEDIA: 744 error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command); 745 break; 746 default: 747 error = ether_ioctl(ifp, command, data); 748 break; 749 } 750 751 return (error); 752} 753 754/* 755 * Generic device handling routines. 756 */ 757int 758nf10bmac_attach(device_t dev) 759{ 760 struct nf10bmac_softc *sc; 761 struct ifnet *ifp; 762 int error; 763 764 sc = device_get_softc(dev); 765 766 mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 767 MTX_DEF); 768 769#ifdef ENABLE_WATCHDOG 770 callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0); 771#endif 772 773 sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK); 774 775 /* Reset the adapter. */ 776 nf10bmac_reset(sc); 777 778 /* Setup interface. */ 779 ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER); 780 if (ifp == NULL) { 781 device_printf(dev, "if_alloc() failed\n"); 782 error = ENOSPC; 783 goto err; 784 } 785 ifp->if_softc = sc; 786 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 787 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST; */ 788 ifp->if_ioctl = nf10bmac_ioctl; 789 ifp->if_start = nf10bmac_start; 790 ifp->if_init = nf10bmac_init; 791 IFQ_SET_MAXLEN(&ifp->if_snd, NF10BMAC_MAX_PKTS - 1); 792 ifp->if_snd.ifq_drv_maxlen = NF10BMAC_MAX_PKTS - 1; 793 IFQ_SET_READY(&ifp->if_snd); 794 795 /* Call media-indepedent attach routine. */ 796 ether_ifattach(ifp, sc->nf10bmac_eth_addr); 797 798 /* Tell the upper layer(s) about vlan mtu support. */ 799 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 800 ifp->if_capabilities |= IFCAP_VLAN_MTU; 801 ifp->if_capenable = ifp->if_capabilities; 802#ifdef DEVICE_POLLING 803 /* We will enable polling by default if no irqs available. See below. */ 804 ifp->if_capabilities |= IFCAP_POLLING; 805#endif 806 807 /* We need more media attention. Fake it! */ 808 ifmedia_init(&sc->nf10bmac_media, 0, nf10bmac_media_change, 809 nf10bmac_media_status); 810 ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL); 811 ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T); 812 813 /* Initialise. */ 814 error = 0; 815 816 /* Hook up interrupts. Well the one. */ 817 if (sc->nf10bmac_rx_irq_res != NULL) { 818 error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res, 819 INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr, 820 sc, &sc->nf10bmac_rx_intrhand); 821 if (error != 0) { 822 device_printf(dev, "enabling RX IRQ failed\n"); 823 ether_ifdetach(ifp); 824 goto err; 825 } 826 } 827 828 if ((ifp->if_capenable & IFCAP_POLLING) != 0 || 829 sc->nf10bmac_rx_irq_res == NULL) { 830#ifdef DEVICE_POLLING 831 /* If not on and no IRQs force it on. */ 832 if (sc->nf10bmac_rx_irq_res == NULL) { 833 ifp->if_capenable |= IFCAP_POLLING; 834 device_printf(dev, 835 "forcing to polling due to no interrupts\n"); 836 } 837 error = ether_poll_register(nf10bmac_poll, ifp); 838 if (error != 0) 839 goto err; 840#else 841 device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n"); 842 error = ENXIO; 843#endif 844 } else { 845 NF10BMAC_RX_INTR_ENABLE(sc); 846 } 847 848err: 849 if (error != 0) 850 nf10bmac_detach(dev); 851 852 return (error); 853} 854 855static int 856nf10bmac_detach(device_t dev) 857{ 858 struct nf10bmac_softc *sc; 859 struct ifnet *ifp; 860 861 sc = device_get_softc(dev); 862 KASSERT(mtx_initialized(&sc->nf10bmac_mtx), 863 ("%s: mutex not initialized", device_get_nameunit(dev))); 864 ifp = sc->nf10bmac_ifp; 865 866#ifdef DEVICE_POLLING 867 if (ifp->if_capenable & IFCAP_POLLING) 868 ether_poll_deregister(ifp); 869#endif 870 871 /* Only cleanup if attach succeeded. */ 872 if (device_is_attached(dev)) { 873 NF10BMAC_LOCK(sc); 874 nf10bmac_stop_locked(sc); 875 NF10BMAC_UNLOCK(sc); 876#ifdef ENABLE_WATCHDOG 877 callout_drain(&sc->nf10bmac_tick); 878#endif 879 ether_ifdetach(ifp); 880 } 881 882 if (sc->nf10bmac_rx_intrhand) 883 bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res, 884 sc->nf10bmac_rx_intrhand); 885 886 if (ifp != NULL) 887 if_free(ifp); 888 ifmedia_removeall(&sc->nf10bmac_media); 889 890 mtx_destroy(&sc->nf10bmac_mtx); 891 892 return (0); 893} 894 895/* Shared with the attachment specific (e.g., fdt) implementation. */ 896void 897nf10bmac_detach_resources(device_t dev) 898{ 899 struct nf10bmac_softc *sc; 900 901 sc = device_get_softc(dev); 902 903 if (sc->nf10bmac_rx_irq_res != NULL) { 904 bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid, 905 sc->nf10bmac_rx_irq_res); 906 sc->nf10bmac_rx_irq_res = NULL; 907 } 908 if (sc->nf10bmac_intr_res != NULL) { 909 bus_release_resource(dev, SYS_RES_MEMORY, 910 sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res); 911 sc->nf10bmac_intr_res = NULL; 912 } 913 if (sc->nf10bmac_rx_mem_res != NULL) { 914 bus_release_resource(dev, SYS_RES_MEMORY, 915 sc->nf10bmac_rx_mem_rid, sc->nf10bmac_rx_mem_res); 916 sc->nf10bmac_rx_mem_res = NULL; 917 } 918 if (sc->nf10bmac_tx_mem_res != NULL) { 919 bus_release_resource(dev, SYS_RES_MEMORY, 920 sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res); 921 sc->nf10bmac_tx_mem_res = NULL; 922 } 923 if (sc->nf10bmac_ctrl_res != NULL) { 924 bus_release_resource(dev, SYS_RES_MEMORY, 925 sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res); 926 sc->nf10bmac_ctrl_res = NULL; 927 } 928} 929 930int 931nf10bmac_detach_dev(device_t dev) 932{ 933 int error; 934 935 error = nf10bmac_detach(dev); 936 if (error) { 937 /* We are basically in undefined state now. */ 938 device_printf(dev, "nf10bmac_detach() failed: %d\n", error); 939 return (error); 940 } 941 942 nf10bmac_detach_resources(dev); 943 944 return (0); 945} 946 947/* end */
| 447 ifp->if_ierrors++; 448 m_freem(m); 449 return (0); 450 } 451 452 m->m_pkthdr.len = m->m_len = len; 453 m->m_pkthdr.rcvif = ifp; 454 ifp->if_ipackets++; 455 456 NF10BMAC_UNLOCK(sc); 457 (*ifp->if_input)(ifp, m); 458 NF10BMAC_LOCK(sc); 459 460 return (1); 461} 462 463 464static int 465nf10bmac_stop_locked(struct nf10bmac_softc *sc) 466{ 467 struct ifnet *ifp; 468 469 NF10BMAC_LOCK_ASSERT(sc); 470 471#ifdef ENABLE_WATCHDOG 472 sc->nf10bmac_watchdog_timer = 0; 473 callout_stop(&sc->nf10bmac_tick); 474#endif 475 476 ifp = sc->nf10bmac_ifp; 477 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 478 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 479 480 sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK; 481 if_link_state_change(ifp, LINK_STATE_DOWN); 482 483 return (0); 484} 485 486static int 487nf10bmac_reset(struct nf10bmac_softc *sc) 488{ 489 490 /* 491 * If we do not have an ether address set, initialize to the same 492 * OUI as NetFPGA-10G Linux driver does (which luckily seems 493 * unallocated). We just change the NIC specific part from 494 * the slightly long "\0NF10C0" to "\0NFBSD". 495 * Oh and we keep the way of setting it from a string as they do. 496 * It's an amazing way to hide it. 497 * XXX-BZ If NetFPGA gets their own OUI we should fix this. 498 */ 499 if (sc->nf10bmac_eth_addr[0] == 0x00 && 500 sc->nf10bmac_eth_addr[1] == 0x00 && 501 sc->nf10bmac_eth_addr[2] == 0x00 && 502 sc->nf10bmac_eth_addr[3] == 0x00 && 503 sc->nf10bmac_eth_addr[4] == 0x00 && 504 sc->nf10bmac_eth_addr[5] == 0x00) { 505 memcpy(&sc->nf10bmac_eth_addr, "\0NFBSD", ETHER_ADDR_LEN); 506 sc->nf10bmac_eth_addr[5] += sc->nf10bmac_unit; 507 } 508 509 return (0); 510} 511 512static void 513nf10bmac_init_locked(struct nf10bmac_softc *sc) 514{ 515 struct ifnet *ifp; 516 uint8_t *eaddr; 517 518 NF10BMAC_LOCK_ASSERT(sc); 519 ifp = sc->nf10bmac_ifp; 520 521 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 522 return; 523 524 /* 525 * Must update the ether address if changed. Given we do not handle 526 * in nf10bmac_ioctl() but it's in the general framework, just always 527 * do it here before nf10bmac_reset(). 528 */ 529 eaddr = IF_LLADDR(sc->nf10bmac_ifp); 530 bcopy(eaddr, &sc->nf10bmac_eth_addr, ETHER_ADDR_LEN); 531 /* XXX-BZ we do not have any way to tell the NIC our ether address. */ 532 533 /* Make things frind to halt, cleanup, ... */ 534 nf10bmac_stop_locked(sc); 535 /* ... reset, ... */ 536 nf10bmac_reset(sc); 537 538 /* Memory rings? DMA engine? MC filter? MII? */ 539 /* Instead drain the FIFO; or at least a possible first packet.. */ 540 nf10bmac_eat_packet_munch_munch(sc); 541 542#ifdef DEVICE_POLLING 543 /* Only enable interrupts if we are not polling. */ 544 if (ifp->if_capenable & IFCAP_POLLING) { 545 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 546 } else 547#endif 548 { 549 NF10BMAC_RX_INTR_ENABLE(sc); 550 } 551 552 ifp->if_drv_flags |= IFF_DRV_RUNNING; 553 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 554 555 /* We have no underlying media, fake link state. */ 556 sc->nf10bmac_flags = NF10BMAC_FLAGS_LINK; /* Always up. */ 557 if_link_state_change(sc->nf10bmac_ifp, LINK_STATE_UP); 558 559#ifdef ENABLE_WATCHDOG 560 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc); 561#endif 562} 563 564static void 565nf10bmac_init(void *xsc) 566{ 567 struct nf10bmac_softc *sc; 568 569 sc = (struct nf10bmac_softc *)xsc; 570 NF10BMAC_LOCK(sc); 571 nf10bmac_init_locked(sc); 572 NF10BMAC_UNLOCK(sc); 573} 574 575#ifdef ENABLE_WATCHDOG 576static void 577nf10bmac_watchdog(struct nf10bmac_softc *sc) 578{ 579 580 NF10BMAC_LOCK_ASSERT(sc); 581 582 if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0) 583 return; 584 585 device_printf(sc->nf10bmac_dev, "watchdog timeout\n"); 586 sc->nf10bmac_ifp->if_oerrors++; 587 588 sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 589 nf10bmac_init_locked(sc); 590 591 if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd)) 592 nf10bmac_start_locked(sc->nf10bmac_ifp); 593} 594 595static void 596nf10bmac_tick(void *xsc) 597{ 598 struct nf10bmac_softc *sc; 599 struct ifnet *ifp; 600 601 sc = (struct nf10bmac_softc *)xsc; 602 NF10BMAC_LOCK_ASSERT(sc); 603 ifp = sc->nf10bmac_ifp; 604 605 nf10bmac_watchdog(sc); 606 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc); 607} 608#endif 609 610static void 611nf10bmac_intr(void *arg) 612{ 613 struct nf10bmac_softc *sc; 614 struct ifnet *ifp; 615 int rx_npkts; 616 617 sc = (struct nf10bmac_softc *)arg; 618 ifp = sc->nf10bmac_ifp; 619 620 NF10BMAC_LOCK(sc); 621#ifdef DEVICE_POLLING 622 if (ifp->if_capenable & IFCAP_POLLING) { 623 NF10BMAC_UNLOCK(sc); 624 return; 625 } 626#endif 627 628 /* NF10BMAC_RX_INTR_DISABLE(sc); */ 629 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 630 631 /* We only have an RX interrupt and no status information. */ 632 rx_npkts = 0; 633 while (rx_npkts < NF10BMAC_MAX_PKTS) { 634 int c; 635 636 c = nf10bmac_rx_locked(sc); 637 rx_npkts += c; 638 if (c == 0) 639 break; 640 } 641 642 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 643 /* Re-enable interrupts. */ 644 NF10BMAC_RX_INTR_ENABLE(sc); 645 646 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 647 nf10bmac_start_locked(ifp); 648 } 649 NF10BMAC_UNLOCK(sc); 650} 651 652 653#ifdef DEVICE_POLLING 654static int 655nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 656{ 657 struct nf10bmac_softc *sc; 658 int rx_npkts = 0; 659 660 sc = ifp->if_softc; 661 NF10BMAC_LOCK(sc); 662 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 663 NF10BMAC_UNLOCK(sc); 664 return (rx_npkts); 665 } 666 667 while (rx_npkts < count) { 668 int c; 669 670 c = nf10bmac_rx_locked(sc); 671 rx_npkts += c; 672 if (c == 0) 673 break; 674 } 675 nf10bmac_start_locked(ifp); 676 677 if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) { 678 /* We currently cannot do much. */ 679 ; 680 } 681 682 NF10BMAC_UNLOCK(sc); 683 return (rx_npkts); 684} 685#else 686#error We only support polling mode 687#endif /* DEVICE_POLLING */ 688 689static int 690nf10bmac_media_change(struct ifnet *ifp __unused) 691{ 692 693 /* Do nothing. */ 694 return (0); 695} 696 697static void 698nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr) 699{ 700 701 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 702 imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX; 703} 704 705static int 706nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 707{ 708 struct nf10bmac_softc *sc; 709 struct ifreq *ifr; 710 int error, mask; 711 712 error = 0; 713 sc = ifp->if_softc; 714 ifr = (struct ifreq *)data; 715 716 switch (command) { 717 case SIOCSIFFLAGS: 718 NF10BMAC_LOCK(sc); 719 if (ifp->if_flags & IFF_UP) { 720 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 721 ((ifp->if_flags ^ sc->nf10bmac_if_flags) & 722 (IFF_PROMISC | IFF_ALLMULTI)) != 0) 723 /* Nothing we can do. */ ; 724 else 725 nf10bmac_init_locked(sc); 726 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 727 nf10bmac_stop_locked(sc); 728 sc->nf10bmac_if_flags = ifp->if_flags; 729 NF10BMAC_UNLOCK(sc); 730 break; 731 case SIOCSIFCAP: 732 NF10BMAC_LOCK(sc); 733 mask = ifr->ifr_reqcap ^ ifp->if_capenable; 734#ifdef DEVICE_POLLING 735 if ((mask & IFCAP_POLLING) != 0 && 736 (IFCAP_POLLING & ifp->if_capabilities) != 0) { 737 ifp->if_capenable ^= IFCAP_POLLING; 738 if ((IFCAP_POLLING & ifp->if_capenable) != 0) { 739 740 error = ether_poll_register(nf10bmac_poll, ifp); 741 if (error != 0) { 742 NF10BMAC_UNLOCK(sc); 743 break; 744 } 745 746 NF10BMAC_RX_INTR_CLEAR_DIS(sc); 747 748 /* 749 * Do not allow disabling of polling if we do 750 * not have interrupts. 751 */ 752 } else if (sc->nf10bmac_rx_irq_res != NULL) { 753 error = ether_poll_deregister(ifp); 754 /* Enable interrupts. */ 755 NF10BMAC_RX_INTR_ENABLE(sc); 756 } else { 757 ifp->if_capenable ^= IFCAP_POLLING; 758 error = EINVAL; 759 } 760 } 761#endif /* DEVICE_POLLING */ 762 NF10BMAC_UNLOCK(sc); 763 break; 764 case SIOCGIFMEDIA: 765 case SIOCSIFMEDIA: 766 error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command); 767 break; 768 default: 769 error = ether_ioctl(ifp, command, data); 770 break; 771 } 772 773 return (error); 774} 775 776/* 777 * Generic device handling routines. 778 */ 779int 780nf10bmac_attach(device_t dev) 781{ 782 struct nf10bmac_softc *sc; 783 struct ifnet *ifp; 784 int error; 785 786 sc = device_get_softc(dev); 787 788 mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 789 MTX_DEF); 790 791#ifdef ENABLE_WATCHDOG 792 callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0); 793#endif 794 795 sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK); 796 797 /* Reset the adapter. */ 798 nf10bmac_reset(sc); 799 800 /* Setup interface. */ 801 ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER); 802 if (ifp == NULL) { 803 device_printf(dev, "if_alloc() failed\n"); 804 error = ENOSPC; 805 goto err; 806 } 807 ifp->if_softc = sc; 808 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 809 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST; */ 810 ifp->if_ioctl = nf10bmac_ioctl; 811 ifp->if_start = nf10bmac_start; 812 ifp->if_init = nf10bmac_init; 813 IFQ_SET_MAXLEN(&ifp->if_snd, NF10BMAC_MAX_PKTS - 1); 814 ifp->if_snd.ifq_drv_maxlen = NF10BMAC_MAX_PKTS - 1; 815 IFQ_SET_READY(&ifp->if_snd); 816 817 /* Call media-indepedent attach routine. */ 818 ether_ifattach(ifp, sc->nf10bmac_eth_addr); 819 820 /* Tell the upper layer(s) about vlan mtu support. */ 821 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 822 ifp->if_capabilities |= IFCAP_VLAN_MTU; 823 ifp->if_capenable = ifp->if_capabilities; 824#ifdef DEVICE_POLLING 825 /* We will enable polling by default if no irqs available. See below. */ 826 ifp->if_capabilities |= IFCAP_POLLING; 827#endif 828 829 /* We need more media attention. Fake it! */ 830 ifmedia_init(&sc->nf10bmac_media, 0, nf10bmac_media_change, 831 nf10bmac_media_status); 832 ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL); 833 ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T); 834 835 /* Initialise. */ 836 error = 0; 837 838 /* Hook up interrupts. Well the one. */ 839 if (sc->nf10bmac_rx_irq_res != NULL) { 840 error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res, 841 INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr, 842 sc, &sc->nf10bmac_rx_intrhand); 843 if (error != 0) { 844 device_printf(dev, "enabling RX IRQ failed\n"); 845 ether_ifdetach(ifp); 846 goto err; 847 } 848 } 849 850 if ((ifp->if_capenable & IFCAP_POLLING) != 0 || 851 sc->nf10bmac_rx_irq_res == NULL) { 852#ifdef DEVICE_POLLING 853 /* If not on and no IRQs force it on. */ 854 if (sc->nf10bmac_rx_irq_res == NULL) { 855 ifp->if_capenable |= IFCAP_POLLING; 856 device_printf(dev, 857 "forcing to polling due to no interrupts\n"); 858 } 859 error = ether_poll_register(nf10bmac_poll, ifp); 860 if (error != 0) 861 goto err; 862#else 863 device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n"); 864 error = ENXIO; 865#endif 866 } else { 867 NF10BMAC_RX_INTR_ENABLE(sc); 868 } 869 870err: 871 if (error != 0) 872 nf10bmac_detach(dev); 873 874 return (error); 875} 876 877static int 878nf10bmac_detach(device_t dev) 879{ 880 struct nf10bmac_softc *sc; 881 struct ifnet *ifp; 882 883 sc = device_get_softc(dev); 884 KASSERT(mtx_initialized(&sc->nf10bmac_mtx), 885 ("%s: mutex not initialized", device_get_nameunit(dev))); 886 ifp = sc->nf10bmac_ifp; 887 888#ifdef DEVICE_POLLING 889 if (ifp->if_capenable & IFCAP_POLLING) 890 ether_poll_deregister(ifp); 891#endif 892 893 /* Only cleanup if attach succeeded. */ 894 if (device_is_attached(dev)) { 895 NF10BMAC_LOCK(sc); 896 nf10bmac_stop_locked(sc); 897 NF10BMAC_UNLOCK(sc); 898#ifdef ENABLE_WATCHDOG 899 callout_drain(&sc->nf10bmac_tick); 900#endif 901 ether_ifdetach(ifp); 902 } 903 904 if (sc->nf10bmac_rx_intrhand) 905 bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res, 906 sc->nf10bmac_rx_intrhand); 907 908 if (ifp != NULL) 909 if_free(ifp); 910 ifmedia_removeall(&sc->nf10bmac_media); 911 912 mtx_destroy(&sc->nf10bmac_mtx); 913 914 return (0); 915} 916 917/* Shared with the attachment specific (e.g., fdt) implementation. */ 918void 919nf10bmac_detach_resources(device_t dev) 920{ 921 struct nf10bmac_softc *sc; 922 923 sc = device_get_softc(dev); 924 925 if (sc->nf10bmac_rx_irq_res != NULL) { 926 bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid, 927 sc->nf10bmac_rx_irq_res); 928 sc->nf10bmac_rx_irq_res = NULL; 929 } 930 if (sc->nf10bmac_intr_res != NULL) { 931 bus_release_resource(dev, SYS_RES_MEMORY, 932 sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res); 933 sc->nf10bmac_intr_res = NULL; 934 } 935 if (sc->nf10bmac_rx_mem_res != NULL) { 936 bus_release_resource(dev, SYS_RES_MEMORY, 937 sc->nf10bmac_rx_mem_rid, sc->nf10bmac_rx_mem_res); 938 sc->nf10bmac_rx_mem_res = NULL; 939 } 940 if (sc->nf10bmac_tx_mem_res != NULL) { 941 bus_release_resource(dev, SYS_RES_MEMORY, 942 sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res); 943 sc->nf10bmac_tx_mem_res = NULL; 944 } 945 if (sc->nf10bmac_ctrl_res != NULL) { 946 bus_release_resource(dev, SYS_RES_MEMORY, 947 sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res); 948 sc->nf10bmac_ctrl_res = NULL; 949 } 950} 951 952int 953nf10bmac_detach_dev(device_t dev) 954{ 955 int error; 956 957 error = nf10bmac_detach(dev); 958 if (error) { 959 /* We are basically in undefined state now. */ 960 device_printf(dev, "nf10bmac_detach() failed: %d\n", error); 961 return (error); 962 } 963 964 nf10bmac_detach_resources(dev); 965 966 return (0); 967} 968 969/* end */
|