static int iicwrite(dev_t dev, struct uio * uio, int ioflag) { device_t iicdev = IIC_DEVICE(minor(dev)); struct iic_softc *sc = IIC_SOFTC(minor(dev)); int sent, error, count; if (!sc || !iicdev || !sc->sc_addr) return (EINVAL); if (sc->sc_count == 0) return (EINVAL); if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, IIC_DONTWAIT))) return (error); count = min(uio->uio_resid, BUFSIZE); uiomove(sc->sc_buffer, count, uio); error = iicbus_block_write(device_get_parent(iicdev), sc->sc_addr, sc->sc_buffer, count, &sent); iicbus_release_bus(device_get_parent(iicdev), iicdev); return(error); }
/* * Generic version of iicbus_transfer that calls the appropriate * routines to accomplish this. See note above about acceptable * buffer addresses. */ int iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { int i, error, lenread, lenwrote, nkid; device_t *children, bus; if ((error = device_get_children(dev, &children, &nkid)) != 0) return (error); if (nkid != 1) { free(children, M_TEMP); return (EIO); } bus = children[0]; free(children, M_TEMP); for (i = 0, error = 0; i < nmsgs && error == 0; i++) { if (msgs[i].flags & IIC_M_RD) error = iicbus_block_read(bus, msgs[i].slave, msgs[i].buf, msgs[i].len, &lenread); else error = iicbus_block_write(bus, msgs[i].slave, msgs[i].buf, msgs[i].len, &lenwrote); } return (error); }
/* * icoutput() */ static int icoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { device_t icdev = devclass_get_device(ic_devclass, ifp->if_dunit); device_t parent = device_get_parent(icdev); struct ic_softc *sc = (struct ic_softc *)device_get_softc(icdev); int len, sent; struct mbuf *mm; u_char *cp; uint32_t hdr = dst->sa_family; ifp->if_flags |= IFF_RUNNING; crit_enter(); /* already sending? */ if (sc->ic_sending) { ifp->if_oerrors ++; goto error; } /* insert header */ bcopy ((char *)&hdr, sc->ic_obuf, ICHDRLEN); cp = sc->ic_obuf + ICHDRLEN; len = 0; mm = m; do { if (len + mm->m_len > sc->ic_if.if_mtu) { /* packet to large */ ifp->if_oerrors ++; goto error; } bcopy(mtod(mm,char *), cp, mm->m_len); cp += mm->m_len; len += mm->m_len; } while ((mm = mm->m_next)); if (ifp->if_bpf) bpf_ptap(ifp->if_bpf, m, &hdr, ICHDRLEN); sc->ic_sending = 1; m_freem(m); crit_exit(); /* send the packet */ if (iicbus_block_write(parent, sc->ic_addr, sc->ic_obuf, len + ICHDRLEN, &sent)) ifp->if_oerrors ++; else { ifp->if_opackets ++; ifp->if_obytes += len; } sc->ic_sending = 0; return (0); error: m_freem(m); crit_exit(); return(0); }
/* * icoutput() */ static int icoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { device_t icdev = devclass_get_device(ic_devclass, ifp->if_unit); device_t parent = device_get_parent(icdev); struct ic_softc *sc = (struct ic_softc *)device_get_softc(icdev); int s, len, sent; struct mbuf *mm; u_char *cp; u_int hdr = dst->sa_family; ifp->if_flags |= IFF_RUNNING; s = splhigh(); /* already sending? */ if (sc->ic_sending) { ifp->if_oerrors ++; goto error; } /* insert header */ bcopy ((char *)&hdr, sc->ic_obuf, ICHDRLEN); cp = sc->ic_obuf + ICHDRLEN; len = 0; mm = m; do { if (len + mm->m_len > sc->ic_if.if_mtu) { /* packet to large */ ifp->if_oerrors ++; goto error; } bcopy(mtod(mm,char *), cp, mm->m_len); cp += mm->m_len; len += mm->m_len; } while ((mm = mm->m_next)); if (ifp->if_bpf) { struct mbuf m0, *n = m; /* * We need to prepend the address family as * a four byte field. Cons up a dummy header * to pacify bpf. This is safe because bpf * will only read from the mbuf (i.e., it won't * try to free it or keep a pointer a to it). */ m0.m_next = m; m0.m_len = sizeof(u_int); m0.m_data = (char *)&hdr; n = &m0; BPF_MTAP(ifp, n); } sc->ic_sending = 1; m_freem(m); splx(s); /* send the packet */ if (iicbus_block_write(parent, sc->ic_addr, sc->ic_obuf, len + ICHDRLEN, &sent)) ifp->if_oerrors ++; else { ifp->if_opackets ++; ifp->if_obytes += len; } sc->ic_sending = 0; return (0); error: m_freem(m); splx(s); return(0); }
/* * icoutput() */ static int icoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct route *ro) { struct ic_softc *sc = ifp->if_softc; device_t icdev = sc->ic_dev; device_t parent = device_get_parent(icdev); int len, sent; struct mbuf *mm; u_char *cp; u_int32_t hdr; /* BPF writes need to be handled specially. */ if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &hdr, sizeof(hdr)); else hdr = dst->sa_family; mtx_lock(&sc->ic_lock); ifp->if_drv_flags |= IFF_DRV_RUNNING; /* already sending? */ if (sc->ic_flags & IC_SENDING) { ifp->if_oerrors++; goto error; } /* insert header */ bcopy ((char *)&hdr, sc->ic_obuf, ICHDRLEN); cp = sc->ic_obuf + ICHDRLEN; len = 0; mm = m; do { if (len + mm->m_len > sc->ic_ifp->if_mtu) { /* packet too large */ ifp->if_oerrors++; goto error; } bcopy(mtod(mm,char *), cp, mm->m_len); cp += mm->m_len; len += mm->m_len; } while ((mm = mm->m_next)); BPF_MTAP2(ifp, &hdr, sizeof(hdr), m); sc->ic_flags |= (IC_SENDING | IC_OBUF_BUSY); m_freem(m); mtx_unlock(&sc->ic_lock); /* send the packet */ if (iicbus_block_write(parent, sc->ic_addr, sc->ic_obuf, len + ICHDRLEN, &sent)) ifp->if_oerrors++; else { ifp->if_opackets++; ifp->if_obytes += len; } mtx_lock(&sc->ic_lock); sc->ic_flags &= ~(IC_SENDING | IC_OBUF_BUSY); if ((sc->ic_flags & (IC_BUFFERS_BUSY | IC_BUFFER_WAITER)) == IC_BUFFER_WAITER) wakeup(&sc); mtx_unlock(&sc->ic_lock); return (0); error: m_freem(m); mtx_unlock(&sc->ic_lock); return(0); }