예제 #1
0
파일: pdq_ifsubr.c 프로젝트: coyizumi/cs111
void
pdq_os_receive_pdu(
    pdq_t *pdq,
    struct mbuf *m,
    size_t pktlen,
    int drop)
{
    pdq_softc_t *sc = pdq->pdq_os_ctx;
    struct ifnet *ifp = PDQ_IFNET(sc);
    struct fddi_header *fh;

    ifp->if_ipackets++;
#if defined(PDQ_BUS_DMA)
    {
	/*
	 * Even though the first mbuf start at the first fddi header octet,
	 * the dmamap starts PDQ_OS_HDR_OFFSET octets earlier.  Any additional
	 * mbufs will start normally.
	 */
	int offset = PDQ_OS_HDR_OFFSET;
	struct mbuf *m0;
	for (m0 = m; m0 != NULL; m0 = m0->m_next, offset = 0) {
	    pdq_os_databuf_sync(sc, m0, offset, m0->m_len, BUS_DMASYNC_POSTREAD);
	    bus_dmamap_unload(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t));
	    bus_dmamap_destroy(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t));
	    m0->m_flags &= ~M_HASRXDMAMAP;
	    M_SETCTX(m0, NULL);
	}
    }
#endif
    m->m_pkthdr.len = pktlen;
    fh = mtod(m, struct fddi_header *);
    if (drop || (fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
	ifp->if_iqdrops++;
	ifp->if_ierrors++;
	PDQ_OS_DATABUF_FREE(pdq, m);
	return;
    }

    m->m_pkthdr.rcvif = ifp;
    PDQ_UNLOCK(sc);
    (*ifp->if_input)(ifp, m);
    PDQ_LOCK(sc);
}
예제 #2
0
/*
 * sco_send(pcb, mbuf)
 *
 *	Send data on SCO pcb.
 *
 * Gross hackage, we just output the packet directly onto the unit queue.
 * This will work fine for one channel per unit, but for more channels it
 * really needs fixing. We set the context so that when the packet is sent,
 * we can drop a record from the socket buffer.
 */
int
sco_send(struct sco_pcb *pcb, struct mbuf *m)
{
	hci_scodata_hdr_t *hdr;
	int plen;

	if (pcb->sp_link == NULL) {
		m_freem(m);
		return EINVAL;
	}

	plen = m->m_pkthdr.len;
	DPRINTFN(10, "%d bytes\n", plen);

	/*
	 * This is a temporary limitation, as USB devices cannot
	 * handle SCO packet sizes that are not an integer number
	 * of Isochronous frames. See ubt(4)
	 */
	if (plen != pcb->sp_mtu) {
		m_freem(m);
		return EMSGSIZE;
	}

	M_PREPEND(m, sizeof(hci_scodata_hdr_t), M_DONTWAIT);
	if (m == NULL)
		return ENOMEM;

	hdr = mtod(m, hci_scodata_hdr_t *);
	hdr->type = HCI_SCO_DATA_PKT;
	hdr->con_handle = htole16(pcb->sp_link->hl_handle);
	hdr->length = plen;

	pcb->sp_pending++;
	M_SETCTX(m, pcb->sp_link);
	hci_output_sco(pcb->sp_link->hl_unit, m);

	return 0;
}
예제 #3
0
파일: pdq_ifsubr.c 프로젝트: coyizumi/cs111
extern struct mbuf *
pdq_os_databuf_alloc(
    pdq_os_ctx_t *sc)
{
    struct mbuf *m;
    bus_dmamap_t map;

    MGETHDR(m, M_NOWAIT, MT_DATA);
    if (m == NULL) {
	printf("%s: can't alloc small buf\n", sc->sc_dev.dv_xname);
	return NULL;
    }
    MCLGET(m, M_NOWAIT);
    if ((m->m_flags & M_EXT) == 0) {
	printf("%s: can't alloc cluster\n", sc->sc_dev.dv_xname);
        m_free(m);
	return NULL;
    }
    m->m_pkthdr.len = m->m_len = PDQ_OS_DATABUF_SIZE;

    if (bus_dmamap_create(sc->sc_dmatag, PDQ_OS_DATABUF_SIZE,
			   1, PDQ_OS_DATABUF_SIZE, 0, BUS_DMA_NOWAIT, &map)) {
	printf("%s: can't create dmamap\n", sc->sc_dev.dv_xname);
	m_free(m);
	return NULL;
    }
    if (bus_dmamap_load_mbuf(sc->sc_dmatag, map, m,
    			     BUS_DMA_READ|BUS_DMA_NOWAIT)) {
	printf("%s: can't load dmamap\n", sc->sc_dev.dv_xname);
	bus_dmamap_destroy(sc->sc_dmatag, map);
	m_free(m);
	return NULL;
    }
    m->m_flags |= M_HASRXDMAMAP;
    M_SETCTX(m, map);
    return m;
}
예제 #4
0
파일: pdq_ifsubr.c 프로젝트: coyizumi/cs111
static void
pdq_ifstart_locked(struct ifnet *ifp)
{
    pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp);
    struct mbuf *m;
    int tx = 0;

    PDQ_LOCK_ASSERT(sc);
    if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
	return;

    if (sc->timer == 0)
	sc->timer = PDQ_OS_TX_TIMEOUT;

    if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
	PDQ_IFNET(sc)->if_drv_flags |= IFF_DRV_OACTIVE;
	return;
    }
    sc->sc_flags |= PDQIF_DOWNCALL;
    for (;; tx = 1) {
	IF_DEQUEUE(&ifp->if_snd, m);
	if (m == NULL)
	    break;
#if defined(PDQ_BUS_DMA) && !defined(PDQ_BUS_DMA_NOTX)
	if ((m->m_flags & M_HASTXDMAMAP) == 0) {
	    bus_dmamap_t map;
	    if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) {
		m->m_data[0] = PDQ_FDDI_PH0;
		m->m_data[1] = PDQ_FDDI_PH1;
		m->m_data[2] = PDQ_FDDI_PH2;
	    }
	    if (!bus_dmamap_create(sc->sc_dmatag, m->m_pkthdr.len, 255,
				   m->m_pkthdr.len, 0, BUS_DMA_NOWAIT, &map)) {
		if (!bus_dmamap_load_mbuf(sc->sc_dmatag, map, m,
					  BUS_DMA_WRITE|BUS_DMA_NOWAIT)) {
		    bus_dmamap_sync(sc->sc_dmatag, map, 0, m->m_pkthdr.len,
				    BUS_DMASYNC_PREWRITE);
		    M_SETCTX(m, map);
		    m->m_flags |= M_HASTXDMAMAP;
		}
	    }
	    if ((m->m_flags & M_HASTXDMAMAP) == 0)
		break;
	}
#else
	if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) {
	    m->m_data[0] = PDQ_FDDI_PH0;
	    m->m_data[1] = PDQ_FDDI_PH1;
	    m->m_data[2] = PDQ_FDDI_PH2;
	}
#endif

	if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE)
	    break;
    }
    if (m != NULL) {
	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
	IF_PREPEND(&ifp->if_snd, m);
    }
    if (tx)
	PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
    sc->sc_flags &= ~PDQIF_DOWNCALL;
}