Date: Wed, 26 Feb 2003 16:58:25 -0500 From: Alain Hebert <ahebert@pubnix.net> To: freebsd-hardware@FreeBSD.ORG Subject: USB Network Drive for -> iPAQ + Familiar Linux + FreeBSD 4.6.2 and Higher Message-ID: <3E5D3881.5223EF0F@pubnix.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------F173E73B457E4DC666B41B3A Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi, This could be interesting... A alternative name could be if_lunet.c 8-} (linux usb net) Why: To interface with the usb-eth module found in Linux and more precisly Familiar v5+ (http://handhelds.org) for iPAQ Model 3100, 3600/3700/3800. Bugs: It works for 10 packets then gets corrupted. Alternative: udbp(4) works but its point to point and its not compatible with the protocol used by usb-eth. (Starting communication with the guys about this.) Already made fixes but need tcpdump from a working setup to complete the fixup of the protocol. Why: Until I can stop working like a monkey and port NetBSD to iPAQ, I'm stuck with Linux. But it does not means I have to run it also for the server side. Have fun... -- Alain Hebert ahebert@pubnix.net PubNIX Inc. P.O. Box 147 Cote Saint Luc, Quebec H4V 2Y3 tel 514-990-5911 http://www.pubnix.net fax 514-990-9443 --------------F173E73B457E4DC666B41B3A Content-Type: text/plain; charset=us-ascii; name="Makefile" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile" # $FreeBSD: src/sys/modules/unet/Makefile,v 1.2 2000/01/28 11:26:30 bde Exp $ S = ${.CURDIR}/../.. .PATH: $S/dev/usb KMOD = if_unet SRCS = if_unet.c opt_bdg.h opt_usb.h device_if.h bus_if.h SRCS += miibus_if.h .include <bsd.kmod.mk> --------------F173E73B457E4DC666B41B3A Content-Type: text/plain; charset=us-ascii; name="if_unet.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="if_unet.c" /*==========================================================================* * * File: . * * Description: . * *--------------------------------------------------------------------------* * * Log: * [date] [username] [comments] * ~ ~ ~ * *--------------------------------------------------------------------------* * $Id$ *--------------------------------------------------------------------------* * Copyright 2002 - Kerner Innovations, Inc. (http://www.kinovations.com) *==========================================================================*/ /*--------------------------------------------------------------------------* * Global Includes *--------------------------------------------------------------------------*/ #include <sys/param.h> #include <sys/systm.h> #include <sys/sockio.h> #include <sys/mbuf.h> #include <sys/malloc.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/random.h> #include <net/if.h> #include <net/if_arp.h> #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/bpf.h> #include <machine/clock.h> #include <sys/bus.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdivar.h> #include <dev/usb/usbdevs.h> #include <dev/usb/usb_ethersubr.h> /*--------------------------------------------------------------------------* * Local Includes *--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------* * Local Defines *--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------* * Debug Macros *--------------------------------------------------------------------------*/ #define DEBUG /*#undef DEBUG*/ #if defined(DEBUG) #define DEBUG_PARMS(fmt,x...) \ printf("I - %s - %s - %d - " fmt "\n", \ __FILE__, \ __PRETTY_FUNCTION__, \ __LINE__, \ x) #define DEBUG_TRACE(fmt,x...) \ printf("T - %s - %s - %d - " fmt "\n", \ __FILE__, \ __PRETTY_FUNCTION__, \ __LINE__, \ x) #define DEBUG_RETURN(fmt,x...) \ printf("O - %s - %s - %d - " fmt "\n", \ __FILE__, \ __PRETTY_FUNCTION__, \ __LINE__, \ x) #else #define DEBUG_PARMS(fmt,x...) #define DEBUG_TRACE(fmt,x...) #define DEBUG_RETURN(fmt,x...) #endif /*--------------------------------------------------------------------------* * Driver Defines *--------------------------------------------------------------------------*/ #define UNET_ENDPT_RX 0x0 #define UNET_ENDPT_TX 0x1 #define UNET_ENDPT_INTR 0x2 #define UNET_ENDPT_MAX 0x3 #define UNET_BUFSZ 1536 #define UNET_RX_LIST_CNT 1 #define UNET_TX_LIST_CNT 1 #define UNET_RXFILT_PROMISC 0x0001 #define UNET_RXFILT_ALLMULTI 0x0002 #define UNET_RXFILT_UNICAST 0x0004 #define UNET_RXFILT_BROADCAST 0x0008 #define UNET_RXFILT_MULTICAST 0x0010 /*--------------------------------------------------------------------------* * Local Typedefs *--------------------------------------------------------------------------*/ typedef struct _unet_chain unet_chain_t; typedef unet_chain_t *punet_chain_t; typedef struct _unet_cdata unet_cdata_t; typedef unet_cdata_t *punet_cdata_t; typedef struct unet_softc unet_softc_t; typedef unet_softc_t *punet_softc_t; struct _unet_chain { punet_softc_t pPrivate; usbd_xfer_handle xfer; char *buf; struct mbuf *mbuf; int idx; }; struct _unet_cdata { unet_chain_t tx_chain[UNET_TX_LIST_CNT]; unet_chain_t rx_chain[UNET_RX_LIST_CNT]; int tx_prod; int tx_cons; int tx_cnt; int rx_prod; }; struct unet_softc { usbd_device_handle udev; usbd_interface_handle iface; int unit; int ed[UNET_ENDPT_MAX]; usbd_pipe_handle ep[UNET_ENDPT_MAX]; u_int8_t gone; int if_flags; struct arpcom arpcom; unet_cdata_t cdata; u_int16_t rxfilt; #if 0 struct kue_ether_desc kue_desc; u_int8_t *kue_mcfilters; struct kue_ether_desc { u_int8_t kue_len; u_int8_t kue_rsvd0; u_int8_t kue_rsvd1; u_int8_t kue_macaddr[ETHER_ADDR_LEN]; u_int8_t kue_etherstats[4]; u_int8_t kue_maxseg[2]; u_int8_t kue_mcastfilt[2]; u_int8_t kue_rsvd2; }; #endif }; struct unet_type { u_int16_t vid; u_int16_t did; }; /*--------------------------------------------------------------------------* * Local Variables *--------------------------------------------------------------------------*/ Static usbd_status _unet_do_request __P( (usbd_device_handle, usb_device_request_t *, void *)); Static int _unet_tx_list_init __P( (punet_softc_t)); Static int _unet_rx_list_init __P( (punet_softc_t)); Static int _unet_newbuf __P( (punet_softc_t, punet_chain_t, struct mbuf *)); Static int _unet_encap __P( (punet_softc_t, struct mbuf *, int)); Static void _unet_rxeof __P( (usbd_xfer_handle, usbd_private_handle, usbd_status)); Static void _unet_txeof __P( (usbd_xfer_handle, usbd_private_handle, usbd_status)); /*Static void _unet_setmulti __P( (punet_softc_t));*/ /*Static void _unet_reset __P( (punet_softc_t));*/ Static void _unet_stop __P( (punet_softc_t)); Static void unet_if_init __P( (void *)); Static void unet_if_start __P( (struct ifnet *)); Static void unet_if_watchdog __P( (struct ifnet *)); Static int unet_if_ioctl __P( (struct ifnet *, u_long, caddr_t)); Static void unet_if_rxstart __P( (struct ifnet *)); Static int unet_match __P( (device_t)); Static int unet_attach __P( (device_t)); Static int unet_detach __P( (device_t)); Static void unet_shutdown __P( (device_t)); Static devclass_t unet_devclass; Static struct usb_qdat unet_qdat; Static struct unet_type unet_devs[] = { { USB_VENDOR_COMPAQ, 0x505a }, /* driver_info: &linuxdev_info, */ { 0, 0 } }; /*--------------------------------------------------------------------------* * Global Variables *--------------------------------------------------------------------------*/ /*extern*/ int usbdebug; /*==========================================================================* * Internal Functions *==========================================================================*/ /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ #if 0 Static usbd_status _unet_do_request(dev,req,data) usbd_device_handle dev; usb_device_request_t *req; void *data; { usbd_xfer_handle xfer; usbd_status err; DEBUG_PARMS("dev: %p, req: %p, data: %p",dev,req,data); xfer = usbd_alloc_xfer(dev); usbd_setup_default_xfer(xfer, dev, 0, 500000, req, data, UGETW(req->wLength), USBD_SHORT_XFER_OK | USBD_NO_TSLEEP, 0); err = usbd_sync_transfer(xfer); usbd_free_xfer(xfer); DEBUG_RETURN("err: %d",err); return(err); } #endif /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _unet_encap(pPrivate,m,idx) punet_softc_t pPrivate; struct mbuf *m; int idx; { int rc, total_len; punet_chain_t pChain; usbd_status err; DEBUG_PARMS("pPrivate: %p, m: %p,idx: %d",pPrivate,m,idx); rc = 0; pChain = &pPrivate->cdata.tx_chain[idx]; /*m_copydata(m,0,m->m_pkthdr.len,pChain->buf+2);*/ m_copydata(m,0,m->m_pkthdr.len,pChain->buf); pChain->mbuf = m; total_len = m->m_pkthdr.len; if ( !(total_len % 64) ) total_len++; /*total_len += 64 - (total_len % 64);*/ /*pChain->buf[0] = (u_int8_t) m->m_pkthdr.len;*/ /*pChain->buf[1] = (u_int8_t) (m->m_pkthdr.len >> 8);*/ usbd_setup_xfer(pChain->xfer, pPrivate->ep[UNET_ENDPT_TX], pChain, pChain->buf, total_len, 0, 10000000, _unet_txeof); if ( (err = usbd_transfer(pChain->xfer)) != USBD_IN_PROGRESS) { DEBUG_TRACE("err: %d",err); _unet_stop(pPrivate); rc = EIO; goto out; } pPrivate->cdata.tx_cnt++; out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _unet_newbuf(pPrivate,pChain,m) punet_softc_t pPrivate; punet_chain_t pChain; struct mbuf *m; { int rc; struct mbuf *m_new; DEBUG_PARMS("pPrivate: %p, pChain: %p, m: %p",pPrivate,pChain,m); rc = 0; m_new = NULL; if (m == NULL) { MGETHDR(m_new,M_DONTWAIT,MT_DATA); if (m_new == NULL) { DEBUG_TRACE("unet%d: no memory for rx list -- packet dropped!", pPrivate->unit); rc = ENOBUFS; goto out; } MCLGET(m_new, M_DONTWAIT); if (!(m_new->m_flags & M_EXT)) { DEBUG_TRACE("unet%d: no memory for rx list -- packet dropped!", pPrivate->unit); m_freem(m_new); rc = ENOBUFS; goto out; } m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; } else { m_new = m; m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; m_new->m_data = m_new->m_ext.ext_buf; } pChain->mbuf = m_new; out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _unet_tx_list_init(pPrivate) punet_softc_t pPrivate; { int i, rc; punet_cdata_t pCData; punet_chain_t pChain; DEBUG_PARMS("pPrivate: %p",pPrivate); rc = 0; pCData = &pPrivate->cdata; for (i = 0; i < UNET_TX_LIST_CNT; i++) { pChain = &pCData->tx_chain[i]; pChain->pPrivate = pPrivate; pChain->idx = i; pChain->mbuf = NULL; if (pChain->xfer == NULL) { pChain->xfer = usbd_alloc_xfer(pPrivate->udev); if (pChain->xfer == NULL) { rc = ENOBUFS; goto out; } } pChain->buf = malloc(UNET_BUFSZ,M_USBDEV,M_NOWAIT); if (pChain->buf == NULL) { rc = ENOBUFS; goto out; } } out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _unet_rx_list_init(pPrivate) punet_softc_t pPrivate; { int i, rc; punet_cdata_t pCData; punet_chain_t pChain; DEBUG_PARMS("pPrivate: %p",pPrivate); rc = 0; pCData = &pPrivate->cdata; for (i = 0; i < UNET_RX_LIST_CNT; i++) { pChain = &pCData->rx_chain[i]; pChain->pPrivate = pPrivate; pChain->idx = i; if (_unet_newbuf(pPrivate, pChain, NULL) == ENOBUFS) { rc = ENOBUFS; goto out; } if (pChain->xfer == NULL) { pChain->xfer = usbd_alloc_xfer(pPrivate->udev); if (pChain->xfer == NULL) { rc = ENOBUFS; goto out; } } } out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void _unet_rxeof(xfer,priv,status) usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { int total_len; struct mbuf *m; struct ifnet *ifp; u_int16_t len; punet_softc_t pPrivate; punet_chain_t pChain; DEBUG_PARMS("xfer: %p, priv: %p, status: %d",xfer,priv,status); total_len = 0; pChain = priv; pPrivate = pChain->pPrivate; ifp = &pPrivate->arpcom.ac_if; if (!(ifp->if_flags & IFF_RUNNING)) goto out; if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) goto out; DEBUG_TRACE("unet%d: usb error on rx: %s", pPrivate->unit, usbd_errstr(status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall(pPrivate->ep[UNET_ENDPT_RX]); goto done; } usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); m = pChain->mbuf; if (total_len <= 1) goto done; /*len = *mtod(m, u_int16_t *);*/ len = m->m_len; /*m_adj(m, sizeof(u_int16_t));*/ total_len = len; if (len < sizeof(struct ether_header)) { ifp->if_ierrors++; goto done; } ifp->if_ipackets++; m->m_pkthdr.rcvif = (struct ifnet * )&unet_qdat; m->m_pkthdr.len = m->m_len = total_len; usb_ether_input(m); goto out; done: usbd_setup_xfer(pChain->xfer, pPrivate->ep[UNET_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), UNET_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _unet_rxeof); usbd_transfer(pChain->xfer); out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void _unet_txeof(xfer,priv,status) usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { int s; usbd_status err; struct ifnet *ifp; punet_softc_t pPrivate; punet_chain_t pChain; DEBUG_PARMS("xfer: %p, priv: %p, status: %d",xfer,priv,status); s = splimp(); pChain = priv; pPrivate = pChain->pPrivate; ifp = &pPrivate->arpcom.ac_if; ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { splx(s); goto out; } DEBUG_TRACE("unet%d: usb error on tx: %s", pPrivate->unit, usbd_errstr(status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall(pPrivate->ep[UNET_ENDPT_TX]); splx(s); goto out; } usbd_get_xfer_status(pChain->xfer,NULL,NULL,NULL,&err); DEBUG_TRACE("err: %d",err); if (pChain->mbuf != NULL) { pChain->mbuf->m_pkthdr.rcvif = ifp; usb_tx_done(pChain->mbuf); DEBUG_TRACE("free mbuf: %p",pChain->mbuf); pChain->mbuf = NULL; } if (err) ifp->if_oerrors++; else ifp->if_opackets++; splx(s); out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void _unet_stop(pPrivate) punet_softc_t pPrivate; { usbd_status err; struct ifnet *ifp; int i; DEBUG_PARMS("pPrivate: %p",pPrivate); ifp = &pPrivate->arpcom.ac_if; ifp->if_timer = 0; if (pPrivate->ep[UNET_ENDPT_RX] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_RX])) ) DEBUG_TRACE("unet%d: abort rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[UNET_ENDPT_RX])) ) DEBUG_TRACE("unet%d: close rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[UNET_ENDPT_RX] = NULL; } if (pPrivate->ep[UNET_ENDPT_TX] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_TX])) ) DEBUG_TRACE("unet%d: abort tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[UNET_ENDPT_TX])) ) DEBUG_TRACE("unet%d: close tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[UNET_ENDPT_TX] = NULL; } if (pPrivate->ep[UNET_ENDPT_INTR] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_INTR])) ) DEBUG_TRACE("unet%d: abort intr pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[UNET_ENDPT_INTR])) ) DEBUG_TRACE("unet%d: close intr pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[UNET_ENDPT_INTR] = NULL; } for (i = 0; i < UNET_RX_LIST_CNT; i++) { if (pPrivate->cdata.rx_chain[i].buf != NULL) { DEBUG_TRACE("freeing buf: %p",pPrivate->cdata.rx_chain[i].buf); free(pPrivate->cdata.rx_chain[i].buf, M_USBDEV); pPrivate->cdata.rx_chain[i].buf = NULL; } if (pPrivate->cdata.rx_chain[i].mbuf != NULL) { DEBUG_TRACE("freeing mbuf: %p",pPrivate->cdata.rx_chain[i].mbuf); m_freem(pPrivate->cdata.rx_chain[i].mbuf); pPrivate->cdata.rx_chain[i].mbuf = NULL; } if (pPrivate->cdata.rx_chain[i].xfer != NULL) { DEBUG_TRACE("freeing xfer: %p",pPrivate->cdata.rx_chain[i].xfer); usbd_free_xfer(pPrivate->cdata.rx_chain[i].xfer); pPrivate->cdata.rx_chain[i].xfer = NULL; } } for (i = 0; i < UNET_TX_LIST_CNT; i++) { if (pPrivate->cdata.tx_chain[i].buf != NULL) { DEBUG_TRACE("freeing buf: %p",pPrivate->cdata.tx_chain[i].buf); free(pPrivate->cdata.tx_chain[i].buf, M_USBDEV); pPrivate->cdata.tx_chain[i].buf = NULL; } if (pPrivate->cdata.tx_chain[i].mbuf != NULL) { DEBUG_TRACE("freeing mbuf: %p",pPrivate->cdata.tx_chain[i].mbuf); m_freem(pPrivate->cdata.tx_chain[i].mbuf); pPrivate->cdata.tx_chain[i].mbuf = NULL; } if (pPrivate->cdata.tx_chain[i].xfer != NULL) { DEBUG_TRACE("freeing xfer: %p",pPrivate->cdata.tx_chain[i].xfer); usbd_free_xfer(pPrivate->cdata.tx_chain[i].xfer); pPrivate->cdata.tx_chain[i].xfer = NULL; } } ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); DEBUG_RETURN("%s","void"); return; } /*==========================================================================* * Ethernet Interface *==========================================================================*/ /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void unet_if_init(sc) void *sc; { int i, s; punet_chain_t pChain; punet_softc_t pPrivate; struct ifnet *ifp; usbd_status err; DEBUG_PARMS("sc: %p",sc); pPrivate= sc; ifp = &pPrivate->arpcom.ac_if; if (ifp->if_flags & IFF_RUNNING) goto out; s = splimp(); #if 0 /* Set MAC address */ kue_ctl(pPrivate, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, pPrivate->arpcom.ac_enaddr, ETHER_ADDR_LEN); #endif pPrivate->rxfilt = UNET_RXFILT_UNICAST|UNET_RXFILT_BROADCAST; if (ifp->if_flags & IFF_PROMISC) pPrivate->rxfilt |= UNET_RXFILT_PROMISC; #if 0 _unet_setword(pPrivate, KUE_CMD_SET_PKT_FILTER, pPrivate->rxfilt); kue_setword(pPrivate, KUE_CMD_SET_URB_SIZE, 64); #endif if (_unet_tx_list_init(pPrivate) == ENOBUFS) { DEBUG_TRACE("unet%d: tx list init failed", pPrivate->unit); splx(s); goto out; } if (_unet_rx_list_init(pPrivate) == ENOBUFS) { DEBUG_TRACE("unet%d: rx list init failed", pPrivate->unit); splx(s); goto out; } #if 0 _unet_setmulti(pPrivate); #endif if ( (err=usbd_open_pipe( pPrivate->iface, pPrivate->ed[UNET_ENDPT_RX], USBD_EXCLUSIVE_USE, &pPrivate->ep[UNET_ENDPT_RX])) ) { DEBUG_TRACE("unet%d: open rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); splx(s); goto out; } if ( (err = usbd_open_pipe( pPrivate->iface, pPrivate->ed[UNET_ENDPT_TX], USBD_EXCLUSIVE_USE, &pPrivate->ep[UNET_ENDPT_TX])) ) { DEBUG_TRACE( "unet%d: open tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); splx(s); goto out; } for(i = 0; i < UNET_RX_LIST_CNT; i++) { pChain = &pPrivate->cdata.rx_chain[i]; usbd_setup_xfer(pChain->xfer, pPrivate->ep[UNET_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), UNET_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _unet_rxeof); usbd_transfer(pChain->xfer); } ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; splx(s); out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void unet_if_start(ifp) struct ifnet *ifp; { punet_softc_t pPrivate; struct mbuf *m_head; DEBUG_PARMS("ifp: %p",ifp); pPrivate= ifp->if_softc; m_head = NULL; if (ifp->if_flags & IFF_OACTIVE) goto out; IF_DEQUEUE(&ifp->if_snd, m_head); if (m_head == NULL) goto out; if (_unet_encap(pPrivate, m_head, 0)) { IF_PREPEND(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; goto out; } if (ifp->if_bpf) bpf_mtap(ifp, m_head); ifp->if_flags |= IFF_OACTIVE; ifp->if_timer = 5; out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void unet_if_watchdog(ifp) struct ifnet *ifp; { punet_softc_t pPrivate; punet_chain_t pChain; usbd_status stat; DEBUG_PARMS("ifp: %p",ifp); pPrivate = ifp->if_softc; ifp->if_oerrors++; DEBUG_TRACE("unet%d: watchdog timeout", pPrivate->unit); pChain = &pPrivate->cdata.tx_chain[0]; usbd_get_xfer_status(pChain->xfer, NULL, NULL, NULL, &stat); _unet_txeof(pChain->xfer, pChain, stat); if (ifp->if_snd.ifq_head != NULL) unet_if_start(ifp); DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int unet_if_ioctl(ifp,command,data) struct ifnet *ifp; u_long command; caddr_t data; { int s, error; punet_softc_t pPrivate; DEBUG_PARMS("ifp: %p, command: %lx, data: %p",ifp,command,data); pPrivate= ifp->if_softc; error = 0; s = splimp(); switch(command) { case SIOCSIFADDR: case SIOCGIFADDR: case SIOCSIFMTU: error = ether_ioctl(ifp, command, data); break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { if ((ifp->if_flags & IFF_RUNNING) && (ifp->if_flags & IFF_PROMISC) && !(pPrivate->if_flags & IFF_PROMISC)) { pPrivate->rxfilt |= UNET_RXFILT_PROMISC; #if 0 _unet_setword( pPrivate, KUE_CMD_SET_PKT_FILTER, pPrivate->rxfilt); #endif } else if ((ifp->if_flags & IFF_RUNNING) && !(ifp->if_flags & IFF_PROMISC) && (pPrivate->if_flags & IFF_PROMISC) ) { pPrivate->rxfilt &= ~UNET_RXFILT_PROMISC; #if 0 _unet_setword( pPrivate, KUE_CMD_SET_PKT_FILTER, pPrivate->rxfilt); #endif } else if (!(ifp->if_flags & IFF_RUNNING)) unet_if_init(pPrivate); } else if (ifp->if_flags & IFF_RUNNING) _unet_stop(pPrivate); pPrivate->if_flags = ifp->if_flags; error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: #if 0 _unet_setmulti(pPrivate); #endif error = 0; break; default: error = EINVAL; break; } splx(s); DEBUG_RETURN("error: %d",error); return(error); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void unet_if_rxstart(ifp) struct ifnet *ifp; { punet_softc_t pPrivate; punet_chain_t pChain; DEBUG_PARMS("ifp: %p",ifp); pPrivate = ifp->if_softc; pChain = &pPrivate->cdata.rx_chain[pPrivate->cdata.rx_prod]; if ( _unet_newbuf(pPrivate,pChain,NULL) == ENOBUFS ) { ifp->if_ierrors++; goto out; } usbd_setup_xfer(pChain->xfer, pPrivate->ep[UNET_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), UNET_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _unet_rxeof); usbd_transfer(pChain->xfer); out: DEBUG_RETURN("%s","void"); return; } /*==========================================================================* * Driver Interface *==========================================================================*/ /*--------------------------------------------------------------------------* * Probe for a KLSI chip. *--------------------------------------------------------------------------*/ USB_MATCH(unet) { int rc; struct unet_type *t; USB_MATCH_START (unet,uaa); DEBUG_PARMS("self: %p",self); rc = UMATCH_NONE; if (!uaa->iface) goto out; for(t = unet_devs; t->vid; t++) { if ((uaa->vendor == t->vid) && (uaa->product == t->did) ) { rc = UMATCH_VENDOR_PRODUCT; break; } } out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * Attach the interface. Allocate softc structures, do setup and * ethernet/BPF attach. *--------------------------------------------------------------------------*/ USB_ATTACH(unet) { char devinfo[1024]; int s; struct ifnet *ifp; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; int i; USB_ATTACH_START (unet,pPrivate,uaa); DEBUG_PARMS("self: %p",self); usbdebug = 65535; s = splimp(); bzero(pPrivate, sizeof(*pPrivate)); pPrivate->iface = uaa->iface; pPrivate->udev = uaa->device; pPrivate->unit = device_get_unit(self); id = usbd_get_interface_descriptor(uaa->iface); usbd_devinfo(uaa->device, 0, devinfo); device_set_desc_copy(self, devinfo); DEBUG_TRACE("%s: %s", USBDEVNAME(self), devinfo); for(i = 0; i < id->bNumEndpoints; i++) { if ( !(ed = usbd_interface2endpoint_descriptor(uaa->iface, i)) ) { DEBUG_TRACE("unet%d: couldn't get ep %d",pPrivate->unit,i); splx(s); USB_ATTACH_ERROR_RETURN; } if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) && ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK) ) { pPrivate->ed[UNET_ENDPT_RX] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint IN & BULK: %d",pPrivate->ed[UNET_ENDPT_RX]); } else if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) && ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)) { pPrivate->ed[UNET_ENDPT_TX] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint OUT & BULK: %d", pPrivate->ed[UNET_ENDPT_RX]); } else if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) && ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) ) { pPrivate->ed[UNET_ENDPT_INTR] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint IN & INTR: %d", pPrivate->ed[UNET_ENDPT_RX]); } } #if 0 pPrivate->mcfilters = malloc( UNET_MCFILTCNT(pPrivate) * ETHER_ADDR_LEN, M_USBDEV, M_NOWAIT); #endif read_random((char *)&pPrivate->arpcom.ac_enaddr,ETHER_ADDR_LEN); pPrivate->arpcom.ac_enaddr[0] &= 0xfe; DEBUG_TRACE("unet%d: Ethernet address: %6D", pPrivate->unit, pPrivate->arpcom.ac_enaddr, ":"); ifp = &pPrivate->arpcom.ac_if; ifp->if_softc = pPrivate; ifp->if_unit = pPrivate->unit; ifp->if_name = "unet"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = unet_if_init; ifp->if_start = unet_if_start; ifp->if_watchdog = unet_if_watchdog; ifp->if_ioctl = unet_if_ioctl; ifp->if_output = ether_output; ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; unet_qdat.ifp = ifp; unet_qdat.if_rxstart = unet_if_rxstart; ether_ifattach(ifp, ETHER_BPF_SUPPORTED); usb_register_netisr(); pPrivate->gone = 0; splx(s); DEBUG_RETURN("%s","success"); USB_ATTACH_SUCCESS_RETURN; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int unet_detach(dev) device_t dev; { punet_softc_t pPrivate; struct ifnet *ifp; int s; DEBUG_PARMS("dev: %p",dev); s = splusb(); pPrivate = device_get_softc(dev); ifp = &pPrivate->arpcom.ac_if; pPrivate->gone = 1; if (ifp != NULL) ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); if (pPrivate->ep[UNET_ENDPT_TX] != NULL) usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_TX]); if (pPrivate->ep[UNET_ENDPT_RX] != NULL) usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_RX]); if (pPrivate->ep[UNET_ENDPT_INTR] != NULL) usbd_abort_pipe(pPrivate->ep[UNET_ENDPT_INTR]); #if 0 if (pPrivate->mcfilters != NULL) free(pPrivate->mcfilters, M_USBDEV); #endif splx(s); usbdebug = 0; DEBUG_RETURN("%d",0); return(0); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void unet_shutdown(dev) device_t dev; { punet_softc_t pPrivate; DEBUG_PARMS("dev: %p",dev); pPrivate = device_get_softc(dev); _unet_stop(pPrivate); DEBUG_RETURN("%s","void"); return; } Static device_method_t unet_methods[] = { DEVMETHOD(device_probe, unet_match), DEVMETHOD(device_attach, unet_attach), DEVMETHOD(device_detach, unet_detach), DEVMETHOD(device_shutdown, unet_shutdown), { 0, 0 } }; Static driver_t unet_driver = { "unet", unet_methods, sizeof(unet_softc_t) }; DRIVER_MODULE(if_unet, uhub, unet_driver, unet_devclass, usbd_driver_load, 0); --------------F173E73B457E4DC666B41B3A-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hardware" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3E5D3881.5223EF0F>