Date: Sat, 15 Mar 2003 22:36:41 -0500 From: Alain Hebert <ahebert@pubnix.net> To: freebsd-hardware@FreeBSD.ORG Subject: Beta: 4.8 and 5.0 compatible driver for usb-eth (linux ethernet for iPAQ) Message-ID: <3E73F149.C8972C3A@pubnix.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------88CC297AF3B3D9A9802D2732 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Here it is. Anybody interested? I need to clean, comment, add licensing, and make man page. (Thanks to Bill Paul <wpaul@ee.columbia.edu> for if_kue.c, which was used as a template for this one, and udbp guys). 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 --------------88CC297AF3B3D9A9802D2732 Content-Type: text/plain; charset=us-ascii; name="if_lueth.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="if_lueth.c" /*==========================================================================* * * File: . * * Description: . * *--------------------------------------------------------------------------* * * Log: * [date] [username] [comments] * ~ ~ ~ * *--------------------------------------------------------------------------* * $Id: if_lueth.c,v 1.1 2003/03/16 03:32:03 aal Exp $ *--------------------------------------------------------------------------* * 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> #define FREEBSD_4 #undef FREEBSD_4 #define FREEBSD_5 /*#undef FREEBSD_4*/ /*--------------------------------------------------------------------------* * 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_DUMP(src,len) \ _lueth_dump(__FILE__, \ __PRETTY_FUNCTION__, \ __LINE__, \ src, \ len) #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...) #define DEBUG_DUMP(src,len) #endif /*--------------------------------------------------------------------------* * Driver Defines *--------------------------------------------------------------------------*/ #define LUETH_ENDPT_RX 0x0 #define LUETH_ENDPT_TX 0x1 #define LUETH_ENDPT_INTR 0x2 #define LUETH_ENDPT_MAX 0x3 #define LUETH_BUFSZ 1536 #define LUETH_RX_LIST_CNT 1 #define LUETH_TX_LIST_CNT 1 #define LUETH_RXFILT_PROMISC 0x0001 #define LUETH_RXFILT_ALLMULTI 0x0002 #define LUETH_RXFILT_UNICAST 0x0004 #define LUETH_RXFILT_BROADCAST 0x0008 #define LUETH_RXFILT_MULTICAST 0x0010 /*--------------------------------------------------------------------------* * Local Typedefs *--------------------------------------------------------------------------*/ typedef struct _lueth_chain lueth_chain_t; typedef lueth_chain_t *plueth_chain_t; typedef struct _lueth_cdata lueth_cdata_t; typedef lueth_cdata_t *plueth_cdata_t; typedef struct lueth_softc lueth_softc_t; typedef lueth_softc_t *plueth_softc_t; struct _lueth_chain { plueth_softc_t pPrivate; usbd_xfer_handle xfer; char *buf; struct mbuf *mbuf; int idx; }; struct _lueth_cdata { lueth_chain_t tx_chain[LUETH_TX_LIST_CNT]; lueth_chain_t rx_chain[LUETH_RX_LIST_CNT]; int tx_prod; int tx_cons; int tx_cnt; int rx_prod; }; struct lueth_softc { usbd_device_handle udev; usbd_interface_handle iface; int unit; int ed[LUETH_ENDPT_MAX]; usbd_pipe_handle ep[LUETH_ENDPT_MAX]; u_int8_t gone; int if_flags; struct arpcom arpcom; lueth_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 lueth_type { u_int16_t vid; u_int16_t did; }; /*--------------------------------------------------------------------------* * Local Variables *--------------------------------------------------------------------------*/ Static int _lueth_tx_list_init __P( (plueth_softc_t)); Static int _lueth_rx_list_init __P( (plueth_softc_t)); Static int _lueth_newbuf __P( (plueth_softc_t, plueth_chain_t, struct mbuf *)); Static int _lueth_encap __P( (plueth_softc_t, struct mbuf *, int)); Static void _lueth_rxeof __P( (usbd_xfer_handle, usbd_private_handle, usbd_status)); Static void _lueth_txeof __P( (usbd_xfer_handle, usbd_private_handle, usbd_status)); /*Static void _lueth_setmulti __P( (plueth_softc_t));*/ /*Static void _lueth_reset __P( (plueth_softc_t));*/ Static void _lueth_stop __P( (plueth_softc_t)); Static void lueth_if_init __P( (void *)); Static void lueth_if_start __P( (struct ifnet *)); Static void lueth_if_watchdog __P( (struct ifnet *)); Static int lueth_if_ioctl __P( (struct ifnet *, u_long, caddr_t)); Static void lueth_if_rxstart __P( (struct ifnet *)); Static int lueth_match __P( (device_t)); Static int lueth_attach __P( (device_t)); Static int lueth_detach __P( (device_t)); Static void lueth_shutdown __P( (device_t)); Static devclass_t lueth_devclass; Static struct usb_qdat lueth_qdat; Static struct lueth_type lueth_devs[] = { { USB_VENDOR_COMPAQ, 0x505a }, /* driver_info: &linuxdev_info, */ { 0, 0 } }; /*--------------------------------------------------------------------------* * Global Variables *--------------------------------------------------------------------------*/ /*extern*/ int usbdebug; MODULE_DEPEND(if_lueth, usb, 1, 1, 1); /*==========================================================================* * Internal Functions *==========================================================================*/ /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ #if 1 /*defined(DEBUG)*/ Static void _lueth_dump ( const char *fname, const char *fctname, const int lnumber, unsigned char *pData, int Length ) { int i, j; unsigned char q1, q2, q3, q4; unsigned int *p, q; for(i = 0, p = (unsigned int *)pData; i < Length; i += 16, p += sizeof(*p)) { printf("%08X | ",(unsigned int) p); for(j = 0; j < sizeof(*p); j++) { if ( (i + (j * sizeof(*p))) < Length ) { q = *(p+j); q1 = (q & 0x000000FF) >> 0; q2 = (q & 0x0000FF00) >> 8; q3 = (q & 0x00FF0000) >> 16; q4 = (q & 0xFF000000) >> 24; printf("%02X %02X %02X %02X ",q1,q2,q3,q4); } else printf(" "); } printf("| "); for(j = 0; j < sizeof(*p); j++ ) { if ( (i + (j * sizeof(*p))) < Length ) { q = *(p+j); q1 = (q & 0x000000FF) >> 0; q2 = (q & 0x0000FF00) >> 8; q3 = (q & 0x00FF0000) >> 16; q4 = (q & 0xFF000000) >> 24; if ( (q1 >= ' ') && (q1 < 127) ) printf("%c",q1); else printf("."); if ( (q2 >= ' ') && (q2 < 127) ) printf("%c",q2); else printf("."); if ( (q3 >= ' ') && (q3 < 127) ) printf("%c",q3); else printf("."); if ( (q4 >= ' ') && (q4 < 127) ) printf("%c",q4); else printf("."); } else printf(" "); } printf("|\n"); } } #endif /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _lueth_encap(pPrivate,m,idx) plueth_softc_t pPrivate; struct mbuf *m; int idx; { int rc, total_len; plueth_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++; DEBUG_DUMP(pChain->buf,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[LUETH_ENDPT_TX], pChain, pChain->buf, total_len, 0, 10000000, _lueth_txeof); if ( (err = usbd_transfer(pChain->xfer)) != USBD_IN_PROGRESS) { DEBUG_TRACE("err: %d",err); _lueth_stop(pPrivate); rc = EIO; goto out; } pPrivate->cdata.tx_cnt++; out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _lueth_newbuf(pPrivate,pChain,m) plueth_softc_t pPrivate; plueth_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("lueth%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("lueth%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 _lueth_tx_list_init(pPrivate) plueth_softc_t pPrivate; { int i, rc; plueth_cdata_t pCData; plueth_chain_t pChain; DEBUG_PARMS("pPrivate: %p",pPrivate); rc = 0; pCData = &pPrivate->cdata; for (i = 0; i < LUETH_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(LUETH_BUFSZ,M_USBDEV,M_NOWAIT); if (pChain->buf == NULL) { rc = ENOBUFS; goto out; } } out: DEBUG_RETURN("rc: %d",rc); return(rc); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int _lueth_rx_list_init(pPrivate) plueth_softc_t pPrivate; { int i, rc; plueth_cdata_t pCData; plueth_chain_t pChain; DEBUG_PARMS("pPrivate: %p",pPrivate); rc = 0; pCData = &pPrivate->cdata; for (i = 0; i < LUETH_RX_LIST_CNT; i++) { pChain = &pCData->rx_chain[i]; pChain->pPrivate = pPrivate; pChain->idx = i; if (_lueth_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 _lueth_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; plueth_softc_t pPrivate; plueth_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("lueth%d: usb error on rx: %s", pPrivate->unit, usbd_errstr(status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall(pPrivate->ep[LUETH_ENDPT_RX]); goto done; } usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); m = pChain->mbuf; if (total_len <= 1) goto done; #if 0 /*len = *mtod(m, u_int16_t *);*/ len = m->m_len; /*m_adj(m, sizeof(u_int16_t));*/ #else len = total_len; #endif total_len = len; if (len < sizeof(struct ether_header)) { ifp->if_ierrors++; goto done; } ifp->if_ipackets++; m->m_pkthdr.rcvif = (struct ifnet * )&lueth_qdat; m->m_pkthdr.len = m->m_len = total_len; DEBUG_DUMP(mtod(pChain->mbuf,char *),total_len); usb_ether_input(m); goto out; done: usbd_setup_xfer(pChain->xfer, pPrivate->ep[LUETH_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), LUETH_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _lueth_rxeof); usbd_transfer(pChain->xfer); out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void _lueth_txeof(xfer,priv,status) usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { int s; usbd_status err; struct ifnet *ifp; plueth_softc_t pPrivate; plueth_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) goto out; DEBUG_TRACE("lueth%d: usb error on tx: %s", pPrivate->unit, usbd_errstr(status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall(pPrivate->ep[LUETH_ENDPT_TX]); 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++; out: DEBUG_RETURN("%s","void"); splx(s); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void _lueth_stop(pPrivate) plueth_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[LUETH_ENDPT_RX] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[LUETH_ENDPT_RX])) ) DEBUG_TRACE("lueth%d: abort rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[LUETH_ENDPT_RX])) ) DEBUG_TRACE("lueth%d: close rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[LUETH_ENDPT_RX] = NULL; } if (pPrivate->ep[LUETH_ENDPT_TX] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[LUETH_ENDPT_TX])) ) DEBUG_TRACE("lueth%d: abort tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[LUETH_ENDPT_TX])) ) DEBUG_TRACE("lueth%d: close tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[LUETH_ENDPT_TX] = NULL; } if (pPrivate->ep[LUETH_ENDPT_INTR] != NULL) { if ( (err = usbd_abort_pipe(pPrivate->ep[LUETH_ENDPT_INTR])) ) DEBUG_TRACE("lueth%d: abort intr pipe failed: %s", pPrivate->unit, usbd_errstr(err)); if ( (err = usbd_close_pipe(pPrivate->ep[LUETH_ENDPT_INTR])) ) DEBUG_TRACE("lueth%d: close intr pipe failed: %s", pPrivate->unit, usbd_errstr(err)); pPrivate->ep[LUETH_ENDPT_INTR] = NULL; } for (i = 0; i < LUETH_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 < LUETH_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 lueth_if_init(sc) void *sc; { int i, s; plueth_chain_t pChain; plueth_softc_t pPrivate; struct ifnet *ifp; usbd_status err; DEBUG_PARMS("sc: %p",sc); pPrivate= sc; ifp = &pPrivate->arpcom.ac_if; s = splimp(); if (ifp->if_flags & IFF_RUNNING) goto out; pPrivate->rxfilt = LUETH_RXFILT_UNICAST|LUETH_RXFILT_BROADCAST; if (ifp->if_flags & IFF_PROMISC) pPrivate->rxfilt |= LUETH_RXFILT_PROMISC; if (_lueth_tx_list_init(pPrivate) == ENOBUFS) { DEBUG_TRACE("lueth%d: tx list init failed", pPrivate->unit); goto out; } if (_lueth_rx_list_init(pPrivate) == ENOBUFS) { DEBUG_TRACE("lueth%d: rx list init failed", pPrivate->unit); goto out; } #if 0 _lueth_setmulti(pPrivate); #endif if ( (err=usbd_open_pipe( pPrivate->iface, pPrivate->ed[LUETH_ENDPT_RX], USBD_EXCLUSIVE_USE, &pPrivate->ep[LUETH_ENDPT_RX])) ) { DEBUG_TRACE("lueth%d: open rx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); goto out; } if ( (err = usbd_open_pipe( pPrivate->iface, pPrivate->ed[LUETH_ENDPT_TX], USBD_EXCLUSIVE_USE, &pPrivate->ep[LUETH_ENDPT_TX])) ) { DEBUG_TRACE("lueth%d: open tx pipe failed: %s", pPrivate->unit, usbd_errstr(err)); goto out; } for(i = 0; i < LUETH_RX_LIST_CNT; i++) { pChain = &pPrivate->cdata.rx_chain[i]; usbd_setup_xfer(pChain->xfer, pPrivate->ep[LUETH_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), LUETH_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _lueth_rxeof); usbd_transfer(pChain->xfer); } ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; out: DEBUG_RETURN("%s","void"); splx(s); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void lueth_if_start(ifp) struct ifnet *ifp; { plueth_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 (_lueth_encap(pPrivate, m_head, 0)) { IF_PREPEND(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; goto out; } #if defined(FREEBSD_4) if (ifp->if_bpf) bpf_mtap(ifp, m_head); #elif defined(FREEBSD_5) BPF_MTAP(ifp, m_head); #else #endif ifp->if_flags |= IFF_OACTIVE; ifp->if_timer = 5; out: DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void lueth_if_watchdog(ifp) struct ifnet *ifp; { plueth_softc_t pPrivate; plueth_chain_t pChain; usbd_status stat; DEBUG_PARMS("ifp: %p",ifp); pPrivate = ifp->if_softc; ifp->if_oerrors++; DEBUG_TRACE("lueth%d: watchdog timeout", pPrivate->unit); pChain = &pPrivate->cdata.tx_chain[0]; usbd_get_xfer_status(pChain->xfer, NULL, NULL, NULL, &stat); _lueth_txeof(pChain->xfer, pChain, stat); if (ifp->if_snd.ifq_head != NULL) lueth_if_start(ifp); DEBUG_RETURN("%s","void"); return; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int lueth_if_ioctl(ifp,command,data) struct ifnet *ifp; u_long command; caddr_t data; { int s, error; plueth_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 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 |= LUETH_RXFILT_PROMISC; #if 0 _lueth_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 &= ~LUETH_RXFILT_PROMISC; #if 0 _lueth_setword( pPrivate, KUE_CMD_SET_PKT_FILTER, pPrivate->rxfilt); #endif } else if (!(ifp->if_flags & IFF_RUNNING)) lueth_if_init(pPrivate); } else if (ifp->if_flags & IFF_RUNNING) _lueth_stop(pPrivate); pPrivate->if_flags = ifp->if_flags; error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: #if 0 _lueth_setmulti(pPrivate); #endif error = 0; break; #if defined(FREEBSD_4) case SIOCSIFADDR: case SIOCGIFADDR: case SIOCSIFMTU: error = ether_ioctl(ifp, command, data); break; default: error = EINVAL; break; #elif defined(FREEBSD_5) default: error = ether_ioctl(ifp, command, data); break; #else #error Huh? #endif } splx(s); DEBUG_RETURN("error: %d",error); return(error); } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static void lueth_if_rxstart(ifp) struct ifnet *ifp; { plueth_softc_t pPrivate; plueth_chain_t pChain; DEBUG_PARMS("ifp: %p",ifp); pPrivate = ifp->if_softc; pChain = &pPrivate->cdata.rx_chain[pPrivate->cdata.rx_prod]; if ( _lueth_newbuf(pPrivate,pChain,NULL) == ENOBUFS ) { ifp->if_ierrors++; goto out; } usbd_setup_xfer(pChain->xfer, pPrivate->ep[LUETH_ENDPT_RX], pChain, mtod(pChain->mbuf,char *), LUETH_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, _lueth_rxeof); usbd_transfer(pChain->xfer); out: DEBUG_RETURN("%s","void"); return; } /*==========================================================================* * Driver Interface *==========================================================================*/ /*--------------------------------------------------------------------------* * Probe for a KLSI chip. *--------------------------------------------------------------------------*/ USB_MATCH(lueth) { int rc; struct lueth_type *t; USB_MATCH_START (lueth,uaa); DEBUG_PARMS("self: %p",self); rc = UMATCH_NONE; if (!uaa->iface) goto out; for(t = lueth_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(lueth) { int i, s; char devinfo[1024]; struct ifnet *ifp; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; USB_ATTACH_START (lueth,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("lueth%d: couldn't get ep %d",pPrivate->unit,i); splx(s); USB_ATTACH_ERROR_RETURN; } if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) && (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) ) { pPrivate->ed[LUETH_ENDPT_RX] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint IN & BULK: %d",pPrivate->ed[LUETH_ENDPT_RX]); } else if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) && (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)) { pPrivate->ed[LUETH_ENDPT_TX] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint OUT & BULK: %d", pPrivate->ed[LUETH_ENDPT_RX]); } else if ((UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) && (UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) ) { pPrivate->ed[LUETH_ENDPT_INTR] = ed->bEndpointAddress; DEBUG_TRACE("Endpoint IN & INTR: %d", pPrivate->ed[LUETH_ENDPT_RX]); } } pPrivate->arpcom.ac_enaddr[0] = 0x00; pPrivate->arpcom.ac_enaddr[1] = 0xa5; pPrivate->arpcom.ac_enaddr[2] = ((unsigned int) pPrivate & 0xFF000000) >> 24; pPrivate->arpcom.ac_enaddr[3] = ((unsigned int) pPrivate & 0x00FF0000) >> 16; pPrivate->arpcom.ac_enaddr[4] = ((unsigned int) pPrivate & 0x0000FF00) >> 8; pPrivate->arpcom.ac_enaddr[5] = ((unsigned int) pPrivate & 0x000000FF) >> 0; pPrivate->arpcom.ac_enaddr[0] &= 0xfe; DEBUG_TRACE("lueth%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 = "lueth"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = lueth_if_init; ifp->if_start = lueth_if_start; ifp->if_watchdog = lueth_if_watchdog; ifp->if_ioctl = lueth_if_ioctl; ifp->if_output = ether_output; ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; lueth_qdat.ifp = ifp; lueth_qdat.if_rxstart = lueth_if_rxstart; #if defined(FREEBSD_4) ether_ifattach(ifp, ETHER_BPF_SUPPORTED); #elif defined(FREEBSD_5) ether_ifattach(ifp, pPrivate->arpcom.ac_enaddr); #else #error Huh? #endif usb_register_netisr(); pPrivate->gone = 0; splx(s); DEBUG_RETURN("%s","success"); USB_ATTACH_SUCCESS_RETURN; } /*--------------------------------------------------------------------------* * *--------------------------------------------------------------------------*/ Static int lueth_detach(dev) device_t dev; { plueth_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) #if defined(FREEBSD_4) ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); #elif defined(FREEBSD_5) ether_ifdetach(ifp); #else #error Huh? #endif if (pPrivate->ep[LUETH_ENDPT_TX] != NULL) usbd_abort_pipe(pPrivate->ep[LUETH_ENDPT_TX]); if (pPrivate->ep[LUETH_ENDPT_RX] != NULL) usbd_abort_pipe(pPrivate->ep[LUETH_ENDPT_RX]); if (pPrivate->ep[LUETH_ENDPT_INTR] != NULL) usbd_abort_pipe(pPrivate->ep[LUETH_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 lueth_shutdown(dev) device_t dev; { plueth_softc_t pPrivate; DEBUG_PARMS("dev: %p",dev); pPrivate = device_get_softc(dev); _lueth_stop(pPrivate); DEBUG_RETURN("%s","void"); return; } Static device_method_t lueth_methods[] = { DEVMETHOD(device_probe, lueth_match), DEVMETHOD(device_attach, lueth_attach), DEVMETHOD(device_detach, lueth_detach), DEVMETHOD(device_shutdown, lueth_shutdown), { 0, 0 } }; Static driver_t lueth_driver = { "lueth", lueth_methods, sizeof(lueth_softc_t) }; DRIVER_MODULE(if_lueth,uhub,lueth_driver,lueth_devclass,usbd_driver_load,0); --------------88CC297AF3B3D9A9802D2732 Content-Type: text/plain; charset=us-ascii; name="Makefile" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile" # $FreeBSD: src/sys/modules/lueth/Makefile,v 1.2 2000/01/28 11:26:30 bde Exp $ S = ${.CURDIR}/../.. .PATH: $S/dev/usb KMOD = if_lueth SRCS = if_lueth.c SRCS += opt_bdg.h opt_usb.h device_if.h bus_if.h miibus_if.h .include <bsd.kmod.mk> reload: -@make clean -@make -@make install -@kldunload if_lueth -@sleep 1 -@logger test -@kldload if_lueth config: -@ifconfig lueth0 192.168.0.201 netmask 255.255.255.0 --------------88CC297AF3B3D9A9802D2732-- 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?3E73F149.C8972C3A>