if_ic.c (161516) | if_ic.c (181305) |
---|---|
1/*- 2 * Copyright (c) 1998, 2001 Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998, 2001 Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/iicbus/if_ic.c 161516 2006-08-21 17:32:50Z imp $"); | 28__FBSDID("$FreeBSD: head/sys/dev/iicbus/if_ic.c 181305 2008-08-04 21:14:24Z jhb $"); |
29 30/* 31 * I2C bus IP driver 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/mbuf.h> 37#include <sys/socket.h> 38#include <sys/filio.h> 39#include <sys/sockio.h> 40#include <sys/kernel.h> | 29 30/* 31 * I2C bus IP driver 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/mbuf.h> 37#include <sys/socket.h> 38#include <sys/filio.h> 39#include <sys/sockio.h> 40#include <sys/kernel.h> |
41#include <sys/lock.h> |
|
41#include <sys/module.h> | 42#include <sys/module.h> |
43#include <sys/mutex.h> |
|
42#include <sys/bus.h> 43#include <sys/time.h> 44#include <sys/malloc.h> 45 46#include <net/if.h> 47#include <net/if_types.h> 48#include <net/netisr.h> 49 --- 16 unchanged lines hidden (view full) --- 66 67#define PCF_MASTER_ADDRESS 0xaa 68 69#define ICHDRLEN sizeof(u_int32_t) 70#define ICMTU 1500 /* default mtu */ 71 72struct ic_softc { 73 struct ifnet *ic_ifp; | 44#include <sys/bus.h> 45#include <sys/time.h> 46#include <sys/malloc.h> 47 48#include <net/if.h> 49#include <net/if_types.h> 50#include <net/netisr.h> 51 --- 16 unchanged lines hidden (view full) --- 68 69#define PCF_MASTER_ADDRESS 0xaa 70 71#define ICHDRLEN sizeof(u_int32_t) 72#define ICMTU 1500 /* default mtu */ 73 74struct ic_softc { 75 struct ifnet *ic_ifp; |
76 device_t ic_dev; |
|
74 75 u_char ic_addr; /* peer I2C address */ 76 | 77 78 u_char ic_addr; /* peer I2C address */ 79 |
77 int ic_sending; | 80 int ic_flags; |
78 79 char *ic_obuf; 80 char *ic_ifbuf; 81 char *ic_cp; 82 83 int ic_xfercnt; 84 85 int ic_iferrs; | 81 82 char *ic_obuf; 83 char *ic_ifbuf; 84 char *ic_cp; 85 86 int ic_xfercnt; 87 88 int ic_iferrs; |
89 90 struct mtx ic_lock; |
|
86}; 87 | 91}; 92 |
93#define IC_SENDING 0x0001 94#define IC_OBUF_BUSY 0x0002 95#define IC_IFBUF_BUSY 0x0004 96#define IC_BUFFERS_BUSY (IC_OBUF_BUSY | IC_IFBUF_BUSY) 97#define IC_BUFFER_WAITER 0x0004 98 |
|
88static devclass_t ic_devclass; 89 90static int icprobe(device_t); 91static int icattach(device_t); 92 93static int icioctl(struct ifnet *, u_long, caddr_t); 94static int icoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 95 struct rtentry *); --- 12 unchanged lines hidden (view full) --- 108}; 109 110static driver_t ic_driver = { 111 "ic", 112 ic_methods, 113 sizeof(struct ic_softc), 114}; 115 | 99static devclass_t ic_devclass; 100 101static int icprobe(device_t); 102static int icattach(device_t); 103 104static int icioctl(struct ifnet *, u_long, caddr_t); 105static int icoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 106 struct rtentry *); --- 12 unchanged lines hidden (view full) --- 119}; 120 121static driver_t ic_driver = { 122 "ic", 123 ic_methods, 124 sizeof(struct ic_softc), 125}; 126 |
127static void 128ic_alloc_buffers(struct ic_softc *sc, int mtu) 129{ 130 char *obuf, *ifbuf; 131 132 obuf = malloc(mtu + ICHDRLEN, M_DEVBUF, M_WAITOK); 133 ifbuf = malloc(mtu + ICHDRLEN, M_DEVBUF, M_WAITOK); 134 135 mtx_lock(&sc->ic_lock); 136 while (sc->ic_flags & IC_BUFFERS_BUSY) { 137 sc->ic_flags |= IC_BUFFER_WAITER; 138 mtx_sleep(sc, &sc->ic_lock, 0, "icalloc", 0); 139 sc->ic_flags &= ~IC_BUFFER_WAITER; 140 } 141 142 free(sc->ic_obuf, M_DEVBUF); 143 free(sc->ic_ifbuf, M_DEVBUF); 144 sc->ic_obuf = obuf; 145 sc->ic_ifbuf = ifbuf; 146 sc->ic_ifp->if_mtu = mtu; 147 mtx_unlock(&sc->ic_lock); 148} 149 |
|
116/* 117 * icprobe() 118 */ 119static int 120icprobe(device_t dev) 121{ 122 return (0); 123} | 150/* 151 * icprobe() 152 */ 153static int 154icprobe(device_t dev) 155{ 156 return (0); 157} |
124 | 158 |
125/* 126 * icattach() 127 */ 128static int 129icattach(device_t dev) 130{ 131 struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev); 132 struct ifnet *ifp; 133 134 ifp = sc->ic_ifp = if_alloc(IFT_PARA); 135 if (ifp == NULL) 136 return (ENOSPC); 137 | 159/* 160 * icattach() 161 */ 162static int 163icattach(device_t dev) 164{ 165 struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev); 166 struct ifnet *ifp; 167 168 ifp = sc->ic_ifp = if_alloc(IFT_PARA); 169 if (ifp == NULL) 170 return (ENOSPC); 171 |
172 mtx_init(&sc->ic_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, 173 MTX_DEF); |
|
138 sc->ic_addr = PCF_MASTER_ADDRESS; /* XXX only PCF masters */ | 174 sc->ic_addr = PCF_MASTER_ADDRESS; /* XXX only PCF masters */ |
175 sc->ic_dev = dev; |
|
139 140 ifp->if_softc = sc; 141 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | 176 177 ifp->if_softc = sc; 178 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); |
142 ifp->if_mtu = ICMTU; 143 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST | 144 IFF_NEEDSGIANT; | 179 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; |
145 ifp->if_ioctl = icioctl; 146 ifp->if_output = icoutput; 147 ifp->if_hdrlen = 0; 148 ifp->if_addrlen = 0; 149 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 150 | 180 ifp->if_ioctl = icioctl; 181 ifp->if_output = icoutput; 182 ifp->if_hdrlen = 0; 183 ifp->if_addrlen = 0; 184 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 185 |
186 ic_alloc_buffers(sc, ICMTU); 187 |
|
151 if_attach(ifp); 152 153 bpfattach(ifp, DLT_NULL, ICHDRLEN); 154 155 return (0); 156} 157 158/* 159 * iciotcl() 160 */ 161static int 162icioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 163{ | 188 if_attach(ifp); 189 190 bpfattach(ifp, DLT_NULL, ICHDRLEN); 191 192 return (0); 193} 194 195/* 196 * iciotcl() 197 */ 198static int 199icioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 200{ |
164 device_t icdev = devclass_get_device(ic_devclass, ifp->if_dunit); | 201 struct ic_softc *sc = ifp->if_softc; 202 device_t icdev = sc->ic_dev; |
165 device_t parent = device_get_parent(icdev); | 203 device_t parent = device_get_parent(icdev); |
166 struct ic_softc *sc = (struct ic_softc *)device_get_softc(icdev); 167 | |
168 struct ifaddr *ifa = (struct ifaddr *)data; 169 struct ifreq *ifr = (struct ifreq *)data; | 204 struct ifaddr *ifa = (struct ifaddr *)data; 205 struct ifreq *ifr = (struct ifreq *)data; |
170 171 u_char *iptr, *optr; | |
172 int error; 173 174 switch (cmd) { 175 176 case SIOCSIFDSTADDR: 177 case SIOCAIFADDR: 178 case SIOCSIFADDR: 179 if (ifa->ifa_addr->sa_family != AF_INET) 180 return (EAFNOSUPPORT); | 206 int error; 207 208 switch (cmd) { 209 210 case SIOCSIFDSTADDR: 211 case SIOCAIFADDR: 212 case SIOCSIFADDR: 213 if (ifa->ifa_addr->sa_family != AF_INET) 214 return (EAFNOSUPPORT); |
215 mtx_lock(&sc->ic_lock); |
|
181 ifp->if_flags |= IFF_UP; | 216 ifp->if_flags |= IFF_UP; |
182 /* FALLTHROUGH */ | 217 goto locked; |
183 case SIOCSIFFLAGS: | 218 case SIOCSIFFLAGS: |
219 mtx_lock(&sc->ic_lock); 220 locked: |
|
184 if ((!(ifp->if_flags & IFF_UP)) && 185 (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 186 187 /* XXX disable PCF */ 188 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | 221 if ((!(ifp->if_flags & IFF_UP)) && 222 (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 223 224 /* XXX disable PCF */ 225 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; |
226 mtx_unlock(&sc->ic_lock); |
|
189 190 /* IFF_UP is not set, try to release the bus anyway */ 191 iicbus_release_bus(parent, icdev); 192 break; 193 } 194 if (((ifp->if_flags & IFF_UP)) && 195 (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) { | 227 228 /* IFF_UP is not set, try to release the bus anyway */ 229 iicbus_release_bus(parent, icdev); 230 break; 231 } 232 if (((ifp->if_flags & IFF_UP)) && 233 (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) { |
234 mtx_unlock(&sc->ic_lock); |
|
196 if ((error = iicbus_request_bus(parent, icdev, 197 IIC_WAIT | IIC_INTR))) 198 return (error); | 235 if ((error = iicbus_request_bus(parent, icdev, 236 IIC_WAIT | IIC_INTR))) 237 return (error); |
199 sc->ic_obuf = malloc(sc->ic_ifp->if_mtu + ICHDRLEN, 200 M_DEVBUF, M_WAITOK); 201 if (!sc->ic_obuf) { 202 iicbus_release_bus(parent, icdev); 203 return (ENOBUFS); 204 } 205 sc->ic_ifbuf = malloc(sc->ic_ifp->if_mtu + ICHDRLEN, 206 M_DEVBUF, M_WAITOK); 207 if (!sc->ic_ifbuf) { 208 iicbus_release_bus(parent, icdev); 209 return (ENOBUFS); 210 } | 238 mtx_lock(&sc->ic_lock); |
211 iicbus_reset(parent, IIC_FASTEST, 0, NULL); 212 ifp->if_drv_flags |= IFF_DRV_RUNNING; 213 } | 239 iicbus_reset(parent, IIC_FASTEST, 0, NULL); 240 ifp->if_drv_flags |= IFF_DRV_RUNNING; 241 } |
242 mtx_unlock(&sc->ic_lock); |
|
214 break; 215 216 case SIOCSIFMTU: | 243 break; 244 245 case SIOCSIFMTU: |
217 /* save previous buffers */ 218 iptr = sc->ic_ifbuf; 219 optr = sc->ic_obuf; 220 221 /* allocate input buffer */ 222 sc->ic_ifbuf = malloc(ifr->ifr_mtu+ICHDRLEN, M_DEVBUF, M_NOWAIT); 223 if (!sc->ic_ifbuf) { 224 sc->ic_ifbuf = iptr; 225 sc->ic_obuf = optr; 226 return (ENOBUFS); 227 } 228 229 /* allocate output buffer */ 230 sc->ic_ifbuf = malloc(ifr->ifr_mtu+ICHDRLEN, M_DEVBUF, M_NOWAIT); 231 if (!sc->ic_obuf) { 232 free(sc->ic_ifbuf,M_DEVBUF); 233 sc->ic_ifbuf = iptr; 234 sc->ic_obuf = optr; 235 return (ENOBUFS); 236 } 237 238 if (iptr) 239 free(iptr,M_DEVBUF); 240 if (optr) 241 free(optr,M_DEVBUF); 242 sc->ic_ifp->if_mtu = ifr->ifr_mtu; | 246 ic_alloc_buffers(sc, ifr->ifr_mtu); |
243 break; 244 245 case SIOCGIFMTU: | 247 break; 248 249 case SIOCGIFMTU: |
250 mtx_lock(&sc->ic_lock); |
|
246 ifr->ifr_mtu = sc->ic_ifp->if_mtu; | 251 ifr->ifr_mtu = sc->ic_ifp->if_mtu; |
252 mtx_unlock(&sc->ic_lock); |
|
247 break; 248 249 case SIOCADDMULTI: 250 case SIOCDELMULTI: 251 if (ifr == 0) 252 return (EAFNOSUPPORT); /* XXX */ 253 switch (ifr->ifr_addr.sa_family) { 254 case AF_INET: --- 10 unchanged lines hidden (view full) --- 265 266/* 267 * icintr() 268 */ 269static void 270icintr(device_t dev, int event, char *ptr) 271{ 272 struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev); | 253 break; 254 255 case SIOCADDMULTI: 256 case SIOCDELMULTI: 257 if (ifr == 0) 258 return (EAFNOSUPPORT); /* XXX */ 259 switch (ifr->ifr_addr.sa_family) { 260 case AF_INET: --- 10 unchanged lines hidden (view full) --- 271 272/* 273 * icintr() 274 */ 275static void 276icintr(device_t dev, int event, char *ptr) 277{ 278 struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev); |
273 int unit = device_get_unit(dev); 274 int s, len; | |
275 struct mbuf *top; | 279 struct mbuf *top; |
276 277 s = splhigh(); | 280 int len; |
278 | 281 |
282 mtx_lock(&sc->ic_lock); 283 |
|
279 switch (event) { 280 281 case INTR_GENERAL: 282 case INTR_START: 283 sc->ic_cp = sc->ic_ifbuf; 284 sc->ic_xfercnt = 0; | 284 switch (event) { 285 286 case INTR_GENERAL: 287 case INTR_START: 288 sc->ic_cp = sc->ic_ifbuf; 289 sc->ic_xfercnt = 0; |
290 sc->ic_flags |= IC_IFBUF_BUSY; |
|
285 break; 286 287 case INTR_STOP: 288 289 /* if any error occured during transfert, 290 * drop the packet */ | 291 break; 292 293 case INTR_STOP: 294 295 /* if any error occured during transfert, 296 * drop the packet */ |
297 sc->ic_flags &= ~IC_IFBUF_BUSY; 298 if ((sc->ic_flags & (IC_BUFFERS_BUSY | IC_BUFFER_WAITER)) == 299 IC_BUFFER_WAITER) 300 wakeup(&sc); |
|
291 if (sc->ic_iferrs) 292 goto err; 293 if ((len = sc->ic_xfercnt) == 0) 294 break; /* ignore */ 295 if (len <= ICHDRLEN) 296 goto err; 297 len -= ICHDRLEN; 298 sc->ic_ifp->if_ipackets++; 299 sc->ic_ifp->if_ibytes += len; 300 BPF_TAP(sc->ic_ifp, sc->ic_ifbuf, len + ICHDRLEN); 301 top = m_devget(sc->ic_ifbuf + ICHDRLEN, len, 0, sc->ic_ifp, 0); | 301 if (sc->ic_iferrs) 302 goto err; 303 if ((len = sc->ic_xfercnt) == 0) 304 break; /* ignore */ 305 if (len <= ICHDRLEN) 306 goto err; 307 len -= ICHDRLEN; 308 sc->ic_ifp->if_ipackets++; 309 sc->ic_ifp->if_ibytes += len; 310 BPF_TAP(sc->ic_ifp, sc->ic_ifbuf, len + ICHDRLEN); 311 top = m_devget(sc->ic_ifbuf + ICHDRLEN, len, 0, sc->ic_ifp, 0); |
302 if (top) | 312 if (top) { 313 mtx_unlock(&sc->ic_lock); |
303 netisr_dispatch(NETISR_IP, top); | 314 netisr_dispatch(NETISR_IP, top); |
315 mtx_lock(&sc->ic_lock); 316 } |
|
304 break; 305 err: | 317 break; 318 err: |
306 printf("ic%d: errors (%d)!\n", unit, sc->ic_iferrs); | 319 if_printf(sc->ic_ifp, "errors (%d)!\n", sc->ic_iferrs); |
307 sc->ic_iferrs = 0; /* reset error count */ 308 sc->ic_ifp->if_ierrors++; 309 break; 310 311 case INTR_RECEIVE: | 320 sc->ic_iferrs = 0; /* reset error count */ 321 sc->ic_ifp->if_ierrors++; 322 break; 323 324 case INTR_RECEIVE: |
312 if (sc->ic_xfercnt >= sc->ic_ifp->if_mtu+ICHDRLEN) { | 325 if (sc->ic_xfercnt >= sc->ic_ifp->if_mtu + ICHDRLEN) { |
313 sc->ic_iferrs++; 314 } else { 315 *sc->ic_cp++ = *ptr; 316 sc->ic_xfercnt++; 317 } 318 break; 319 320 case INTR_NOACK: /* xfer terminated by master */ --- 6 unchanged lines hidden (view full) --- 327 case INTR_ERROR: 328 sc->ic_iferrs++; 329 break; 330 331 default: 332 panic("%s: unknown event (%d)!", __func__, event); 333 } 334 | 326 sc->ic_iferrs++; 327 } else { 328 *sc->ic_cp++ = *ptr; 329 sc->ic_xfercnt++; 330 } 331 break; 332 333 case INTR_NOACK: /* xfer terminated by master */ --- 6 unchanged lines hidden (view full) --- 340 case INTR_ERROR: 341 sc->ic_iferrs++; 342 break; 343 344 default: 345 panic("%s: unknown event (%d)!", __func__, event); 346 } 347 |
335 splx(s); | 348 mtx_unlock(&sc->ic_lock); |
336 return; 337} 338 339/* 340 * icoutput() 341 */ 342static int 343icoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 344 struct rtentry *rt) 345{ | 349 return; 350} 351 352/* 353 * icoutput() 354 */ 355static int 356icoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 357 struct rtentry *rt) 358{ |
346 device_t icdev = devclass_get_device(ic_devclass, ifp->if_dunit); | 359 struct ic_softc *sc = ifp->if_softc; 360 device_t icdev = sc->ic_dev; |
347 device_t parent = device_get_parent(icdev); | 361 device_t parent = device_get_parent(icdev); |
348 struct ic_softc *sc = (struct ic_softc *)device_get_softc(icdev); 349 350 int s, len, sent; | 362 int len, sent; |
351 struct mbuf *mm; 352 u_char *cp; 353 u_int32_t hdr; 354 355 /* BPF writes need to be handled specially. */ 356 if (dst->sa_family == AF_UNSPEC) 357 bcopy(dst->sa_data, &hdr, sizeof(hdr)); 358 else 359 hdr = dst->sa_family; 360 | 363 struct mbuf *mm; 364 u_char *cp; 365 u_int32_t hdr; 366 367 /* BPF writes need to be handled specially. */ 368 if (dst->sa_family == AF_UNSPEC) 369 bcopy(dst->sa_data, &hdr, sizeof(hdr)); 370 else 371 hdr = dst->sa_family; 372 |
373 mtx_lock(&sc->ic_lock); |
|
361 ifp->if_drv_flags |= IFF_DRV_RUNNING; 362 | 374 ifp->if_drv_flags |= IFF_DRV_RUNNING; 375 |
363 s = splhigh(); 364 | |
365 /* already sending? */ | 376 /* already sending? */ |
366 if (sc->ic_sending) { | 377 if (sc->ic_flags & IC_SENDING) { |
367 ifp->if_oerrors++; 368 goto error; 369 } 370 371 /* insert header */ 372 bcopy ((char *)&hdr, sc->ic_obuf, ICHDRLEN); 373 374 cp = sc->ic_obuf + ICHDRLEN; 375 len = 0; 376 mm = m; 377 do { 378 if (len + mm->m_len > sc->ic_ifp->if_mtu) { | 378 ifp->if_oerrors++; 379 goto error; 380 } 381 382 /* insert header */ 383 bcopy ((char *)&hdr, sc->ic_obuf, ICHDRLEN); 384 385 cp = sc->ic_obuf + ICHDRLEN; 386 len = 0; 387 mm = m; 388 do { 389 if (len + mm->m_len > sc->ic_ifp->if_mtu) { |
379 /* packet to large */ | 390 /* packet too large */ |
380 ifp->if_oerrors++; 381 goto error; 382 } 383 384 bcopy(mtod(mm,char *), cp, mm->m_len); 385 cp += mm->m_len; 386 len += mm->m_len; 387 388 } while ((mm = mm->m_next)); 389 390 BPF_MTAP2(ifp, &hdr, sizeof(hdr), m); 391 | 391 ifp->if_oerrors++; 392 goto error; 393 } 394 395 bcopy(mtod(mm,char *), cp, mm->m_len); 396 cp += mm->m_len; 397 len += mm->m_len; 398 399 } while ((mm = mm->m_next)); 400 401 BPF_MTAP2(ifp, &hdr, sizeof(hdr), m); 402 |
392 sc->ic_sending = 1; | 403 sc->ic_flags |= (IC_SENDING | IC_OBUF_BUSY); |
393 394 m_freem(m); | 404 405 m_freem(m); |
395 splx(s); | 406 mtx_unlock(&sc->ic_lock); |
396 397 /* send the packet */ 398 if (iicbus_block_write(parent, sc->ic_addr, sc->ic_obuf, 399 len + ICHDRLEN, &sent)) 400 401 ifp->if_oerrors++; 402 else { 403 ifp->if_opackets++; 404 ifp->if_obytes += len; | 407 408 /* send the packet */ 409 if (iicbus_block_write(parent, sc->ic_addr, sc->ic_obuf, 410 len + ICHDRLEN, &sent)) 411 412 ifp->if_oerrors++; 413 else { 414 ifp->if_opackets++; 415 ifp->if_obytes += len; |
405 } | 416 } |
406 | 417 |
407 sc->ic_sending = 0; | 418 mtx_lock(&sc->ic_lock); 419 sc->ic_flags &= ~(IC_SENDING | IC_OBUF_BUSY); 420 if ((sc->ic_flags & (IC_BUFFERS_BUSY | IC_BUFFER_WAITER)) == 421 IC_BUFFER_WAITER) 422 wakeup(&sc); 423 mtx_unlock(&sc->ic_lock); |
408 409 return (0); 410 411error: 412 m_freem(m); | 424 425 return (0); 426 427error: 428 m_freem(m); |
413 splx(s); | 429 mtx_unlock(&sc->ic_lock); |
414 415 return(0); 416} 417 418DRIVER_MODULE(ic, iicbus, ic_driver, ic_devclass, 0, 0); 419MODULE_DEPEND(ic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 420MODULE_VERSION(ic, 1); | 430 431 return(0); 432} 433 434DRIVER_MODULE(ic, iicbus, ic_driver, ic_devclass, 0, 0); 435MODULE_DEPEND(ic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 436MODULE_VERSION(ic, 1); |