示例#1
0
文件: iic.c 项目: MarginC/kame
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);
}
示例#2
0
/*
 * 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);
}
示例#3
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_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);
}
示例#4
0
文件: if_ic.c 项目: MarginC/kame
/*
 * 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);
}
示例#5
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);
}