Deleted Added
full compact
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);