Пример #1
0
static void
fwe_start(struct ifnet *ifp)
{
	struct fwe_softc *fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
	int s;

	FWEDEBUG(ifp, "starting\n");

	if (fwe->dma_ch < 0) {
		struct mbuf	*m = NULL;

		FWEDEBUG(ifp, "not ready\n");

		s = splimp();
		do {
			IF_DEQUEUE(&ifp->if_snd, m);
			if (m != NULL)
				m_freem(m);
			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
		} while (m != NULL);
		splx(s);

		return;
	}

	s = splimp();
	ifp->if_drv_flags |= IFF_DRV_OACTIVE;

	if (ifp->if_snd.ifq_len != 0)
		fwe_as_output(fwe, ifp);

	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
	splx(s);
}
Пример #2
0
static void
fwe_output_callback(struct fw_xfer *xfer)
{
	struct fwe_softc *fwe;
	struct ifnet *ifp;
	int s;

	fwe = (struct fwe_softc *)xfer->sc;
	ifp = fwe->eth_softc.ifp;
	/* XXX error check */
	FWEDEBUG(ifp, "resp = %d\n", xfer->resp);
	if (xfer->resp != 0)
		ifp->if_oerrors ++;
		
	m_freem(xfer->mbuf);
	fw_xfer_unload(xfer);

	s = splimp();
	FWE_LOCK(fwe);
	STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
	FWE_UNLOCK(fwe);
	splx(s);

	/* for queue full */
	if (ifp->if_snd.ifq_head != NULL)
		fwe_start(ifp);
}
Пример #3
0
static void
fwe_ref(caddr_t buf, u_int size)
{
	int *p;

	FWEDEBUG("fwe_ref: called\n");
	p = (int *)buf;
	(*p) ++;
}
Пример #4
0
static void
fwe_free(caddr_t buf, u_int size)
{
	int *p;
	FWEDEBUG("fwe_free:\n");
	p = (int *)buf;
	(*p) --;
	if (*p < 1)
		free(buf, M_DEVBUF);
}
Пример #5
0
static void
fwe_init(void *arg)
{
	struct fwe_softc *fwe = ((struct fwe_eth_softc *)arg)->fwe;
	struct firewire_comm *fc;
	struct ifnet *ifp = &fwe->fwe_if;
	struct fw_xferq *xferq;
	int i;

	FWEDEBUG("initializing %s%d\n", ifp->if_name, ifp->if_unit);

	/* XXX keep promiscoud mode */
	ifp->if_flags |= IFF_PROMISC;

	fc = fwe->fd.fc;
#define START 0
	if (fwe->dma_ch < 0) {
		xferq = NULL;
		for (i = START; i < fc->nisodma; i ++) {
			xferq = fc->ir[i];
			if ((xferq->flag & FWXFERQ_OPEN) == 0)
				break;
		}

		if (xferq == NULL) {
			printf("no free dma channel\n");
			return;
		}
		fwe->dma_ch = i;
		fwe->stream_ch = stream_ch;
		fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;
		/* allocate DMA channel and init packet mode */
		xferq->flag |= FWXFERQ_OPEN | FWXFERQ_PACKET;
		xferq->flag |= fwe->stream_ch & 0xff;
		/* register fwe_input handler */
		xferq->sc = (caddr_t) fwe;
		xferq->hand = fwe_as_input;
		xferq->flag |= FWXFERQ_HANDLER;
	} else
		xferq = fc->ir[fwe->dma_ch];


	/* start dma */
	if ((xferq->flag & FWXFERQ_RUNNING) == 0)
		fc->irx_enable(fc, fwe->dma_ch);

	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	FWE_POLL_REGISTER(fwe_poll, fwe, ifp);
#if 0
	/* attempt to start output */
	fwe_start(ifp);
#endif
}
Пример #6
0
static void
fwe_start(struct ifnet *ifp)
{
	struct fwe_softc *fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
	int s;

	FWEDEBUG(ifp, "starting\n");

	if (fwe->dma_ch < 0) {
		struct mbuf	*m = NULL;

		FWEDEBUG(ifp, "not ready\n");

		s = splimp();
		do {
			IF_DEQUEUE(&ifp->if_snd, m);
			if (m != NULL)
				m_freem(m);
			ifp->if_oerrors ++;
		} while (m != NULL);
		splx(s);

		return;
	}

	s = splimp();
#if defined(__FreeBSD__)
	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
#else
	ifp->if_flags |= IFF_OACTIVE;
#endif

	if (ifp->if_snd.ifq_len != 0)
		fwe_as_output(fwe, ifp);

#if defined(__FreeBSD__)
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
#else
	ifp->if_flags &= ~IFF_OACTIVE;
#endif
	splx(s);
}
Пример #7
0
static void
fwe_start(struct ifnet *ifp)
{
	struct fwe_softc *fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
	int s;

#if 1
	FWEDEBUG("%s%d starting\n", ifp->if_name, ifp->if_unit);

	if (fwe->dma_ch < 0) {
		struct mbuf	*m = NULL;

		FWEDEBUG("%s%d not ready.\n", ifp->if_name, ifp->if_unit);

		s = splimp();
		do {
			IF_DEQUEUE(&ifp->if_snd, m);
			if (m != NULL)
				m_freem(m);
			ifp->if_oerrors ++;
		} while (m != NULL);
		splx(s);

		return;
	}

#endif
	s = splimp();
	ifp->if_flags |= IFF_OACTIVE;

	if (ifp->if_snd.ifq_len != 0)
		fwe_as_output(fwe, ifp);

	ifp->if_flags &= ~IFF_OACTIVE;
	splx(s);
}
Пример #8
0
static void
fwe_output_callback(struct fw_xfer *xfer)
{
	struct fwe_softc *fwe;
	struct ifnet *ifp;

	fwe = (struct fwe_softc *)xfer->sc;
	/* XXX error check */
	FWEDEBUG("resp = %d\n", xfer->resp);
	m_freem(xfer->mbuf);
	xfer->send.buf = NULL;
	fw_xfer_free(xfer);
#if 1
	/* XXX for queue full */
	ifp = &fwe->fwe_if;
	if (ifp->if_snd.ifq_head != NULL)
		fwe_start(ifp);
#endif
}
Пример #9
0
/* Async. stream output */
static void
fwe_as_input(struct fw_xferq *xferq)
{
	struct mbuf *m, *m0;
	struct ifnet *ifp;
	struct fwe_softc *fwe;
	struct fw_bulkxfer *sxfer;
	struct fw_pkt *fp;
	u_char *c;
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	struct ether_header *eh;
#endif

	fwe = (struct fwe_softc *)xferq->sc;
	ifp = fwe->eth_softc.ifp;

	/* We do not need a lock here because the bottom half is serialized */
	while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
		STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
		fp = mtod(sxfer->mbuf, struct fw_pkt *);
		if (fwe->fd.fc->irx_post != NULL)
			fwe->fd.fc->irx_post(fwe->fd.fc, fp->mode.ld);
		m = sxfer->mbuf;

		/* insert new rbuf */
		sxfer->mbuf = m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
		if (m0 != NULL) {
			m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size;
			STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link);
		} else
			printf("%s: m_getcl failed\n", __FUNCTION__);

		if (sxfer->resp != 0 || fp->mode.stream.len <
		    ETHER_ALIGN + sizeof(struct ether_header)) {
			m_freem(m);
			ifp->if_ierrors ++;
			continue;
		}

		m->m_data += HDR_LEN + ETHER_ALIGN;
		c = mtod(m, u_char *);
#if defined(__DragonFly__) || __FreeBSD_version < 500000
		eh = (struct ether_header *)c;
		m->m_data += sizeof(struct ether_header);
		m->m_len = m->m_pkthdr.len = fp->mode.stream.len - ETHER_ALIGN
		    - sizeof(struct ether_header);
#else
		m->m_len = m->m_pkthdr.len = fp->mode.stream.len - ETHER_ALIGN;
#endif
		m->m_pkthdr.rcvif = ifp;
#if 0
		FWEDEBUG(ifp, "%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n",
			 c[0], c[1], c[2], c[3], c[4], c[5],
			 c[6], c[7], c[8], c[9], c[10], c[11],
			 c[12], c[13], c[14], c[15],
			 c[16], c[17], c[18], c[19],
			 c[20], c[21], c[22], c[23],
			 c[20], c[21], c[22], c[23]
		 );
#endif
#if defined(__DragonFly__) || __FreeBSD_version < 500000
		ether_input(ifp, eh, m);
#else
		(*ifp->if_input)(ifp, m);
#endif
		ifp->if_ipackets ++;
	}
	if (STAILQ_FIRST(&xferq->stfree) != NULL)
		fwe->fd.fc->irx_enable(fwe->fd.fc, fwe->dma_ch);
}
Пример #10
0
static void
fwe_init(void *arg)
{
	struct fwe_softc *fwe = ((struct fwe_eth_softc *)arg)->fwe;
	struct firewire_comm *fc;
	struct ifnet *ifp = fwe->eth_softc.ifp;
	struct fw_xferq *xferq;
	struct fw_xfer *xfer;
	struct mbuf *m;
	int i;

	FWEDEBUG(ifp, "initializing\n");

	/* XXX keep promiscoud mode */
	ifp->if_flags |= IFF_PROMISC;

	fc = fwe->fd.fc;
	if (fwe->dma_ch < 0) {
		fwe->dma_ch = fw_open_isodma(fc, /* tx */0);
		if (fwe->dma_ch < 0)
			return;
		xferq = fc->ir[fwe->dma_ch];
		xferq->flag |= FWXFERQ_EXTBUF |
				FWXFERQ_HANDLER | FWXFERQ_STREAM;
		fwe->stream_ch = stream_ch;
		fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;
		xferq->flag &= ~0xff;
		xferq->flag |= fwe->stream_ch & 0xff;
		/* register fwe_input handler */
		xferq->sc = (caddr_t) fwe;
		xferq->hand = fwe_as_input;
		xferq->bnchunk = rx_queue_len;
		xferq->bnpacket = 1;
		xferq->psize = MCLBYTES;
		xferq->queued = 0;
		xferq->buf = NULL;
		xferq->bulkxfer = (struct fw_bulkxfer *) malloc(
			sizeof(struct fw_bulkxfer) * xferq->bnchunk,
							M_FWE, M_WAITOK);
		if (xferq->bulkxfer == NULL) {
			printf("if_fwe: malloc failed\n");
			return;
		}
		STAILQ_INIT(&xferq->stvalid);
		STAILQ_INIT(&xferq->stfree);
		STAILQ_INIT(&xferq->stdma);
		xferq->stproc = NULL;
		for (i = 0; i < xferq->bnchunk; i ++) {
			m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
			xferq->bulkxfer[i].mbuf = m;
			m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
			STAILQ_INSERT_TAIL(&xferq->stfree,
					&xferq->bulkxfer[i], link);
		}
		STAILQ_INIT(&fwe->xferlist);
		for (i = 0; i < TX_MAX_QUEUE; i++) {
			xfer = fw_xfer_alloc(M_FWE);
			if (xfer == NULL)
				break;
			xfer->send.spd = tx_speed;
			xfer->fc = fwe->fd.fc;
			xfer->sc = (caddr_t)fwe;
			xfer->hand = fwe_output_callback;
			STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
		}
	} else
		xferq = fc->ir[fwe->dma_ch];


	/* start dma */
	if ((xferq->flag & FWXFERQ_RUNNING) == 0)
		fc->irx_enable(fc, fwe->dma_ch);

#if defined(__FreeBSD__)
	ifp->if_drv_flags |= IFF_DRV_RUNNING;
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
#else
	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;
#endif

#if 0
	/* attempt to start output */
	fwe_start(ifp);
#endif
}
Пример #11
0
static int
fwe_attach(device_t dev)
{
	struct fwe_softc *fwe;
	struct ifnet *ifp;
	int unit, s;
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	u_char *eaddr;
#else
	u_char eaddr[6];
#endif
	struct fw_eui64 *eui;

	fwe = ((struct fwe_softc *)device_get_softc(dev));
	unit = device_get_unit(dev);

	bzero(fwe, sizeof(struct fwe_softc));
	mtx_init(&fwe->mtx, "fwe", NULL, MTX_DEF);
	/* XXX */
	fwe->stream_ch = stream_ch;
	fwe->dma_ch = -1;

	fwe->fd.fc = device_get_ivars(dev);
	if (tx_speed < 0)
		tx_speed = fwe->fd.fc->speed;

	fwe->fd.dev = dev;
	fwe->fd.post_explore = NULL;
	fwe->eth_softc.fwe = fwe;

	fwe->pkt_hdr.mode.stream.tcode = FWTCODE_STREAM;
	fwe->pkt_hdr.mode.stream.sy = 0;
	fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;

	/* generate fake MAC address: first and last 3bytes from eui64 */
#define LOCAL (0x02)
#define GROUP (0x01)
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	eaddr = &IFP2ENADDR(fwe->eth_softc.ifp)[0];
#endif


	eui = &fwe->fd.fc->eui;
	eaddr[0] = (FW_EUI64_BYTE(eui, 0) | LOCAL) & ~GROUP;
	eaddr[1] = FW_EUI64_BYTE(eui, 1);
	eaddr[2] = FW_EUI64_BYTE(eui, 2);
	eaddr[3] = FW_EUI64_BYTE(eui, 5);
	eaddr[4] = FW_EUI64_BYTE(eui, 6);
	eaddr[5] = FW_EUI64_BYTE(eui, 7);
	printf("if_fwe%d: Fake Ethernet address: "
		"%02x:%02x:%02x:%02x:%02x:%02x\n", unit,
		eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);

	/* fill the rest and attach interface */	
	ifp = fwe->eth_softc.ifp = if_alloc(IFT_ETHER);
	if (ifp == NULL) {
		device_printf(dev, "can not if_alloc()\n");
		return (ENOSPC);
	}
	ifp->if_softc = &fwe->eth_softc;

#if __FreeBSD_version >= 501113 || defined(__DragonFly__)
	if_initname(ifp, device_get_name(dev), unit);
#else
	ifp->if_unit = unit;
	ifp->if_name = "fwe";
#endif
	ifp->if_init = fwe_init;
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	ifp->if_output = ether_output;
#endif
	ifp->if_start = fwe_start;
	ifp->if_ioctl = fwe_ioctl;
	ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
	ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;

	s = splimp();
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	ether_ifattach(ifp, 1);
#else
	ether_ifattach(ifp, eaddr);
#endif
	splx(s);

        /* Tell the upper layer(s) we support long frames. */
	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_POLLING;
	ifp->if_capenable |= IFCAP_VLAN_MTU;
#endif


	FWEDEBUG(ifp, "interface created\n");
	return 0;
}
Пример #12
0
/* Async. stream output */
static void
fwe_as_input(struct fw_xferq *xferq)
{
	struct mbuf *m;
	struct ether_header *eh;
	struct ifnet *ifp;
	struct fw_xfer *xfer;
	struct fwe_softc *fwe;
	u_char *c;
	int len;
	caddr_t p;

	fwe = (struct fwe_softc *)xferq->sc;
	ifp = &fwe->fwe_if;
#if 0
	FWE_POLL_REGISTER(fwe_poll, fwe, ifp);
#endif
	while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) {
		STAILQ_REMOVE_HEAD(&xferq->q, link);
		xferq->queued --;
		MGETHDR(m, M_DONTWAIT, MT_DATA);
		if (m == NULL) {
			printf("MGETHDR failed\n");
			fw_xfer_free(xfer);
			return;
		}
		len = xfer->recv.off + xfer->recv.len;
		FWEDEBUG("fwe_as_input len=%d\n", len);
#if __FreeBSD_version >= 500000
		MEXTADD(m, xfer->recv.buf, len, fwe_free, NULL, 0, EXT_NET_DRV);
#else
		m->m_flags |= M_EXT;
		m->m_ext.ext_buf = xfer->recv.buf;
		m->m_ext.ext_size = len;
		m->m_ext.ext_free = fwe_free;
		m->m_ext.ext_ref = fwe_ref;
		*((int *)m->m_ext.ext_buf) = 1;  /* XXX refcount */
#endif
		p = xfer->recv.buf + xfer->recv.off + HDR_LEN + ALIGN_PAD;
		eh = (struct ether_header *)p;
#if __FreeBSD_version >= 500000
		len -= xfer->recv.off + HDR_LEN + ALIGN_PAD;
#else
		p += sizeof(struct ether_header);
		len -= xfer->recv.off + HDR_LEN + ALIGN_PAD
						+ sizeof(struct ether_header);
#endif
		m->m_data = p;
		m->m_len = m->m_pkthdr.len = len;
		m->m_pkthdr.rcvif = ifp;
		c = (char *)eh;
#if 0
		FWEDEBUG("%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n",
			 c[0], c[1], c[2], c[3], c[4], c[5],
			 c[6], c[7], c[8], c[9], c[10], c[11],
			 c[12], c[13], c[14], c[15],
			 c[16], c[17], c[18], c[19],
			 c[20], c[21], c[22], c[23],
			 c[20], c[21], c[22], c[23]
		 );
#endif
#if __FreeBSD_version >= 500000
		(*ifp->if_input)(ifp, m);
#else
		ether_input(ifp, eh, m);
#endif
		ifp->if_ipackets ++;

		xfer->recv.buf = NULL;
		fw_xfer_free(xfer);
	}
}
Пример #13
0
static void
fwe_free(void *buf, void *args)
{
	FWEDEBUG("fwe_free:\n");
	free(buf, M_DEVBUF);
}
Пример #14
0
static int
fwe_attach(device_t dev)
{
	struct fwe_softc *fwe;
	struct ifnet *ifp;
	int unit, s;
	u_char *eaddr;

	fwe = ((struct fwe_softc *)device_get_softc(dev));
	unit = device_get_unit(dev);

	bzero(fwe, sizeof(struct fwe_softc));
	/* XXX */
	fwe->stream_ch = stream_ch;
	fwe->dma_ch = -1;

	fwe->fd.fc = device_get_ivars(dev);
	fwe->fd.dev = dev;
	fwe->fd.post_explore = NULL;
	fwe->eth_softc.fwe = fwe;

	fwe->pkt_hdr.mode.stream.tcode = FWTCODE_STREAM;
	fwe->pkt_hdr.mode.stream.sy = 0;
	fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;

	/* generate fake MAC address: first and last 3bytes from eui64 */
#define LOCAL (0x02)
#define GROUP (0x01)
	eaddr = &fwe->eth_softc.arpcom.ac_enaddr[0];
	eaddr[0] = (fwe->fd.fc->eui[0] | LOCAL) & ~GROUP;
	eaddr[1] = fwe->fd.fc->eui[1];
	eaddr[2] = fwe->fd.fc->eui[2];
	eaddr[3] = fwe->fd.fc->eui[5];
	eaddr[4] = fwe->fd.fc->eui[6];
	eaddr[5] = fwe->fd.fc->eui[7];
	printf("if_fwe%d: Fake Ethernet address: "
		"%02x:%02x:%02x:%02x:%02x:%02x\n", unit,
		eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);

	/* fill the rest and attach interface */	
	ifp = &fwe->fwe_if;
	ifp->if_softc = &fwe->eth_softc;

	ifp->if_unit = unit;
	ifp->if_name = "fwe";
	ifp->if_init = fwe_init;
	ifp->if_output = ether_output;
	ifp->if_start = fwe_start;
	ifp->if_ioctl = fwe_ioctl;
	ifp->if_mtu = ETHERMTU;
	ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
	ifp->if_snd.ifq_maxlen = FWMAXQUEUE - 1;

	s = splimp();
#if __FreeBSD_version >= 500000
	ether_ifattach(ifp, eaddr);
#else
	ether_ifattach(ifp, 1);
#endif
	splx(s);

        /* Tell the upper layer(s) we support long frames. */
	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
#if __FreeBSD_version >= 500000
	ifp->if_capabilities |= IFCAP_VLAN_MTU;
#endif

	ifp->if_snd.ifq_maxlen = MAX_QUEUED - 1;

	FWEDEBUG("interface %s%d created.\n", ifp->if_name, ifp->if_unit);
	return 0;
}