version 1.38, 2013/01/05 01:30:15 |
version 1.38.18.1, 2016/09/06 20:33:08 |
Line 85 Static int cdce_rx_list_init(struct cdc |
|
Line 85 Static int cdce_rx_list_init(struct cdc |
|
Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, |
Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, |
struct mbuf *); |
struct mbuf *); |
Static int cdce_encap(struct cdce_softc *, struct mbuf *, int); |
Static int cdce_encap(struct cdce_softc *, struct mbuf *, int); |
Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); |
Static void cdce_rxeof(struct usbd_xfer *, void *, usbd_status); |
Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); |
Static void cdce_txeof(struct usbd_xfer *, void *, usbd_status); |
Static void cdce_start(struct ifnet *); |
Static void cdce_start(struct ifnet *); |
Static int cdce_ioctl(struct ifnet *, u_long, void *); |
Static int cdce_ioctl(struct ifnet *, u_long, void *); |
Static void cdce_init(void *); |
Static void cdce_init(void *); |
Line 120 CFATTACH_DECL_NEW(cdce, sizeof(struct cd |
|
Line 120 CFATTACH_DECL_NEW(cdce, sizeof(struct cd |
|
int |
int |
cdce_match(device_t parent, cfdata_t match, void *aux) |
cdce_match(device_t parent, cfdata_t match, void *aux) |
{ |
{ |
struct usbif_attach_arg *uaa = aux; |
struct usbif_attach_arg *uiaa = aux; |
|
|
if (cdce_lookup(uaa->vendor, uaa->product) != NULL) |
if (cdce_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL) |
return (UMATCH_VENDOR_PRODUCT); |
return UMATCH_VENDOR_PRODUCT; |
|
|
if (uaa->class == UICLASS_CDC && uaa->subclass == |
if (uiaa->uiaa_class == UICLASS_CDC && uiaa->uiaa_subclass == |
UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) |
UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) |
return (UMATCH_IFACECLASS_GENERIC); |
return UMATCH_IFACECLASS_GENERIC; |
|
|
return (UMATCH_NONE); |
return UMATCH_NONE; |
} |
} |
|
|
void |
void |
cdce_attach(device_t parent, device_t self, void *aux) |
cdce_attach(device_t parent, device_t self, void *aux) |
{ |
{ |
struct cdce_softc *sc = device_private(self); |
struct cdce_softc *sc = device_private(self); |
struct usbif_attach_arg *uaa = aux; |
struct usbif_attach_arg *uiaa = aux; |
char *devinfop; |
char *devinfop; |
int s; |
int s; |
struct ifnet *ifp; |
struct ifnet *ifp; |
usbd_device_handle dev = uaa->device; |
struct usbd_device *dev = uiaa->uiaa_device; |
const struct cdce_type *t; |
const struct cdce_type *t; |
usb_interface_descriptor_t *id; |
usb_interface_descriptor_t *id; |
usb_endpoint_descriptor_t *ed; |
usb_endpoint_descriptor_t *ed; |
Line 161 cdce_attach(device_t parent, device_t se |
|
Line 161 cdce_attach(device_t parent, device_t se |
|
aprint_normal_dev(self, "%s\n", devinfop); |
aprint_normal_dev(self, "%s\n", devinfop); |
usbd_devinfo_free(devinfop); |
usbd_devinfo_free(devinfop); |
|
|
sc->cdce_udev = uaa->device; |
sc->cdce_udev = uiaa->uiaa_device; |
sc->cdce_ctl_iface = uaa->iface; |
sc->cdce_ctl_iface = uiaa->uiaa_iface; |
|
|
t = cdce_lookup(uaa->vendor, uaa->product); |
t = cdce_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product); |
if (t) |
if (t) |
sc->cdce_flags = t->cdce_flags; |
sc->cdce_flags = t->cdce_flags; |
|
|
Line 179 cdce_attach(device_t parent, device_t se |
|
Line 179 cdce_attach(device_t parent, device_t se |
|
} |
} |
data_ifcno = ud->bSlaveInterface[0]; |
data_ifcno = ud->bSlaveInterface[0]; |
|
|
for (i = 0; i < uaa->nifaces; i++) { |
for (i = 0; i < uiaa->uiaa_nifaces; i++) { |
if (uaa->ifaces[i] != NULL) { |
if (uiaa->uiaa_ifaces[i] != NULL) { |
id = usbd_get_interface_descriptor( |
id = usbd_get_interface_descriptor( |
uaa->ifaces[i]); |
uiaa->uiaa_ifaces[i]); |
if (id != NULL && id->bInterfaceNumber == |
if (id != NULL && id->bInterfaceNumber == |
data_ifcno) { |
data_ifcno) { |
sc->cdce_data_iface = uaa->ifaces[i]; |
sc->cdce_data_iface = uiaa->uiaa_ifaces[i]; |
uaa->ifaces[i] = NULL; |
uiaa->uiaa_ifaces[i] = NULL; |
} |
} |
} |
} |
} |
} |
Line 315 cdce_detach(device_t self, int flags) |
|
Line 315 cdce_detach(device_t self, int flags) |
|
|
|
if (!sc->cdce_attached) { |
if (!sc->cdce_attached) { |
splx(s); |
splx(s); |
return (0); |
return 0; |
} |
} |
|
|
if (ifp->if_flags & IFF_RUNNING) |
if (ifp->if_flags & IFF_RUNNING) |
Line 328 cdce_detach(device_t self, int flags) |
|
Line 328 cdce_detach(device_t self, int flags) |
|
sc->cdce_attached = 0; |
sc->cdce_attached = 0; |
splx(s); |
splx(s); |
|
|
return (0); |
return 0; |
} |
} |
|
|
Static void |
Static void |
Line 378 cdce_encap(struct cdce_softc *sc, struct |
|
Line 378 cdce_encap(struct cdce_softc *sc, struct |
|
} |
} |
c->cdce_mbuf = m; |
c->cdce_mbuf = m; |
|
|
usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, |
usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, m->m_pkthdr.len + extra, |
m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, |
USBD_FORCE_SHORT_XFER, 10000, cdce_txeof); |
10000, cdce_txeof); |
|
err = usbd_transfer(c->cdce_xfer); |
err = usbd_transfer(c->cdce_xfer); |
if (err != USBD_IN_PROGRESS) { |
if (err != USBD_IN_PROGRESS) { |
cdce_stop(sc); |
cdce_stop(sc); |
return (EIO); |
return EIO; |
} |
} |
|
|
sc->cdce_cdata.cdce_tx_cnt++; |
sc->cdce_cdata.cdce_tx_cnt++; |
|
|
return (0); |
return 0; |
} |
} |
|
|
Static void |
Static void |
Line 406 cdce_stop(struct cdce_softc *sc) |
|
Line 405 cdce_stop(struct cdce_softc *sc) |
|
if (err) |
if (err) |
printf("%s: abort rx pipe failed: %s\n", |
printf("%s: abort rx pipe failed: %s\n", |
device_xname(sc->cdce_dev), usbd_errstr(err)); |
device_xname(sc->cdce_dev), usbd_errstr(err)); |
err = usbd_close_pipe(sc->cdce_bulkin_pipe); |
|
if (err) |
|
printf("%s: close rx pipe failed: %s\n", |
|
device_xname(sc->cdce_dev), usbd_errstr(err)); |
|
sc->cdce_bulkin_pipe = NULL; |
|
} |
} |
|
|
if (sc->cdce_bulkout_pipe != NULL) { |
if (sc->cdce_bulkout_pipe != NULL) { |
Line 418 cdce_stop(struct cdce_softc *sc) |
|
Line 412 cdce_stop(struct cdce_softc *sc) |
|
if (err) |
if (err) |
printf("%s: abort tx pipe failed: %s\n", |
printf("%s: abort tx pipe failed: %s\n", |
device_xname(sc->cdce_dev), usbd_errstr(err)); |
device_xname(sc->cdce_dev), usbd_errstr(err)); |
err = usbd_close_pipe(sc->cdce_bulkout_pipe); |
|
if (err) |
|
printf("%s: close tx pipe failed: %s\n", |
|
device_xname(sc->cdce_dev), usbd_errstr(err)); |
|
sc->cdce_bulkout_pipe = NULL; |
|
} |
} |
|
|
for (i = 0; i < CDCE_RX_LIST_CNT; i++) { |
for (i = 0; i < CDCE_RX_LIST_CNT; i++) { |
Line 431 cdce_stop(struct cdce_softc *sc) |
|
Line 420 cdce_stop(struct cdce_softc *sc) |
|
sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; |
sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; |
} |
} |
if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { |
if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { |
usbd_free_xfer |
usbd_destroy_xfer |
(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); |
(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); |
sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; |
sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; |
} |
} |
Line 443 cdce_stop(struct cdce_softc *sc) |
|
Line 432 cdce_stop(struct cdce_softc *sc) |
|
sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; |
sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; |
} |
} |
if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { |
if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { |
usbd_free_xfer( |
usbd_destroy_xfer( |
sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); |
sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); |
sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; |
sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; |
} |
} |
} |
} |
|
|
|
if (sc->cdce_bulkin_pipe != NULL) { |
|
err = usbd_close_pipe(sc->cdce_bulkin_pipe); |
|
if (err) |
|
printf("%s: close rx pipe failed: %s\n", |
|
device_xname(sc->cdce_dev), usbd_errstr(err)); |
|
sc->cdce_bulkin_pipe = NULL; |
|
} |
|
|
|
if (sc->cdce_bulkout_pipe != NULL) { |
|
err = usbd_close_pipe(sc->cdce_bulkout_pipe); |
|
if (err) |
|
printf("%s: close tx pipe failed: %s\n", |
|
device_xname(sc->cdce_dev), usbd_errstr(err)); |
|
sc->cdce_bulkout_pipe = NULL; |
|
} |
|
|
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
} |
} |
|
|
Line 461 cdce_ioctl(struct ifnet *ifp, u_long com |
|
Line 466 cdce_ioctl(struct ifnet *ifp, u_long com |
|
int s, error = 0; |
int s, error = 0; |
|
|
if (sc->cdce_dying) |
if (sc->cdce_dying) |
return (EIO); |
return EIO; |
|
|
s = splnet(); |
s = splnet(); |
|
|
Line 511 cdce_ioctl(struct ifnet *ifp, u_long com |
|
Line 516 cdce_ioctl(struct ifnet *ifp, u_long com |
|
if (error == ENETRESET) |
if (error == ENETRESET) |
error = 0; |
error = 0; |
|
|
return (error); |
return error; |
} |
} |
|
|
Static void |
Static void |
Line 540 cdce_init(void *xsc) |
|
Line 545 cdce_init(void *xsc) |
|
|
|
s = splnet(); |
s = splnet(); |
|
|
if (cdce_tx_list_init(sc) == ENOBUFS) { |
|
printf("%s: tx list init failed\n", device_xname(sc->cdce_dev)); |
|
splx(s); |
|
return; |
|
} |
|
|
|
if (cdce_rx_list_init(sc) == ENOBUFS) { |
|
printf("%s: rx list init failed\n", device_xname(sc->cdce_dev)); |
|
splx(s); |
|
return; |
|
} |
|
|
|
/* Maybe set multicast / broadcast here??? */ |
/* Maybe set multicast / broadcast here??? */ |
|
|
err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, |
err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, |
Line 572 cdce_init(void *xsc) |
|
Line 565 cdce_init(void *xsc) |
|
return; |
return; |
} |
} |
|
|
|
if (cdce_tx_list_init(sc)) { |
|
printf("%s: tx list init failed\n", device_xname(sc->cdce_dev)); |
|
splx(s); |
|
return; |
|
} |
|
|
|
if (cdce_rx_list_init(sc)) { |
|
printf("%s: rx list init failed\n", device_xname(sc->cdce_dev)); |
|
splx(s); |
|
return; |
|
} |
|
|
for (i = 0; i < CDCE_RX_LIST_CNT; i++) { |
for (i = 0; i < CDCE_RX_LIST_CNT; i++) { |
c = &sc->cdce_cdata.cdce_rx_chain[i]; |
c = &sc->cdce_cdata.cdce_rx_chain[i]; |
usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, |
|
c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, |
usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, CDCE_BUFSZ, |
USBD_NO_TIMEOUT, cdce_rxeof); |
USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cdce_rxeof); |
usbd_transfer(c->cdce_xfer); |
usbd_transfer(c->cdce_xfer); |
} |
} |
|
|
Line 596 cdce_newbuf(struct cdce_softc *sc, struc |
|
Line 601 cdce_newbuf(struct cdce_softc *sc, struc |
|
if (m_new == NULL) { |
if (m_new == NULL) { |
printf("%s: no memory for rx list " |
printf("%s: no memory for rx list " |
"-- packet dropped!\n", device_xname(sc->cdce_dev)); |
"-- packet dropped!\n", device_xname(sc->cdce_dev)); |
return (ENOBUFS); |
return ENOBUFS; |
} |
} |
MCLGET(m_new, M_DONTWAIT); |
MCLGET(m_new, M_DONTWAIT); |
if (!(m_new->m_flags & M_EXT)) { |
if (!(m_new->m_flags & M_EXT)) { |
printf("%s: no memory for rx list " |
printf("%s: no memory for rx list " |
"-- packet dropped!\n", device_xname(sc->cdce_dev)); |
"-- packet dropped!\n", device_xname(sc->cdce_dev)); |
m_freem(m_new); |
m_freem(m_new); |
return (ENOBUFS); |
return ENOBUFS; |
} |
} |
m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; |
m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; |
} else { |
} else { |
Line 612 cdce_newbuf(struct cdce_softc *sc, struc |
|
Line 617 cdce_newbuf(struct cdce_softc *sc, struc |
|
m_new->m_data = m_new->m_ext.ext_buf; |
m_new->m_data = m_new->m_ext.ext_buf; |
} |
} |
c->cdce_mbuf = m_new; |
c->cdce_mbuf = m_new; |
return (0); |
return 0; |
} |
} |
|
|
Static int |
Static int |
Line 628 cdce_rx_list_init(struct cdce_softc *sc) |
|
Line 633 cdce_rx_list_init(struct cdce_softc *sc) |
|
c->cdce_sc = sc; |
c->cdce_sc = sc; |
c->cdce_idx = i; |
c->cdce_idx = i; |
if (cdce_newbuf(sc, c, NULL) == ENOBUFS) |
if (cdce_newbuf(sc, c, NULL) == ENOBUFS) |
return (ENOBUFS); |
return ENOBUFS; |
if (c->cdce_xfer == NULL) { |
if (c->cdce_xfer == NULL) { |
c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); |
int err = usbd_create_xfer(sc->cdce_bulkin_pipe, |
if (c->cdce_xfer == NULL) |
CDCE_BUFSZ, USBD_SHORT_XFER_OK, 0, &c->cdce_xfer); |
return (ENOBUFS); |
if (err) |
c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, |
return err; |
CDCE_BUFSZ); |
c->cdce_buf = usbd_get_buffer(c->cdce_xfer); |
if (c->cdce_buf == NULL) |
|
return (ENOBUFS); |
|
} |
} |
} |
} |
|
|
return (0); |
return 0; |
} |
} |
|
|
Static int |
Static int |
Line 657 cdce_tx_list_init(struct cdce_softc *sc) |
|
Line 660 cdce_tx_list_init(struct cdce_softc *sc) |
|
c->cdce_idx = i; |
c->cdce_idx = i; |
c->cdce_mbuf = NULL; |
c->cdce_mbuf = NULL; |
if (c->cdce_xfer == NULL) { |
if (c->cdce_xfer == NULL) { |
c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); |
int err = usbd_create_xfer(sc->cdce_bulkout_pipe, |
if (c->cdce_xfer == NULL) |
CDCE_BUFSZ, USBD_FORCE_SHORT_XFER, 0, |
return (ENOBUFS); |
&c->cdce_xfer); |
c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); |
if (err) |
if (c->cdce_buf == NULL) |
return err; |
return (ENOBUFS); |
c->cdce_buf = usbd_get_buffer(c->cdce_xfer); |
} |
} |
} |
} |
|
|
return (0); |
return 0; |
} |
} |
|
|
Static void |
Static void |
cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) |
cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) |
{ |
{ |
struct cdce_chain *c = priv; |
struct cdce_chain *c = priv; |
struct cdce_softc *sc = c->cdce_sc; |
struct cdce_softc *sc = c->cdce_sc; |
|
|
|
|
done: |
done: |
/* Setup new transfer. */ |
/* Setup new transfer. */ |
usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, |
usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, CDCE_BUFSZ, |
CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, |
USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cdce_rxeof); |
cdce_rxeof); |
|
usbd_transfer(c->cdce_xfer); |
usbd_transfer(c->cdce_xfer); |
} |
} |
|
|
Static void |
Static void |
cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, |
cdce_txeof(struct usbd_xfer *xfer, void *priv, |
usbd_status status) |
usbd_status status) |
{ |
{ |
struct cdce_chain *c = priv; |
struct cdce_chain *c = priv; |