From a9f34b79757de68cdd3f951077be0dd65da6354c Mon Sep 17 00:00:00 2001 From: cvs2git Date: Sun, 7 Mar 2010 17:11:24 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'R_20100307_p0'. Sprout from base 2009-04-22 22:06:58 UTC Till Straumann ' - importing updated version from SLAC as of 20090422' Cherrypick from master 2010-03-07 17:11:23 UTC Till Straumann '2010-03-07 Till Straumann ': bsd_eth_drivers/.cvsignore bsd_eth_drivers/ChangeLog bsd_eth_drivers/Makefile.am bsd_eth_drivers/if_bge/.cvsignore bsd_eth_drivers/if_bge/Makefile.am bsd_eth_drivers/if_bge/if_bge.c bsd_eth_drivers/if_bge/if_bgereg.h bsd_eth_drivers/if_em/.cvsignore bsd_eth_drivers/if_em/Makefile.am bsd_eth_drivers/if_em/e1000_manage.c bsd_eth_drivers/if_em/e1000_manage.h bsd_eth_drivers/if_em/e1000_osdep.h bsd_eth_drivers/if_em/if_em.c bsd_eth_drivers/if_fxp/.cvsignore bsd_eth_drivers/if_fxp/Makefile.am bsd_eth_drivers/if_fxp/if_fxp.c bsd_eth_drivers/if_fxp/if_fxpvar.h bsd_eth_drivers/if_le/.cvsignore bsd_eth_drivers/if_pcn/.cvsignore bsd_eth_drivers/if_pcn/if_pcn.c bsd_eth_drivers/if_re/.cvsignore bsd_eth_drivers/if_re/Makefile.am bsd_eth_drivers/if_re/if_re.c bsd_eth_drivers/if_re/if_rl.c bsd_eth_drivers/if_re/if_rlreg.h bsd_eth_drivers/libbsdport/.cvsignore bsd_eth_drivers/libbsdport/Makefile.am bsd_eth_drivers/libbsdport/alldrv.c bsd_eth_drivers/libbsdport/bus.h bsd_eth_drivers/libbsdport/callout.h bsd_eth_drivers/libbsdport/devicet.c bsd_eth_drivers/libbsdport/ifmedia.c bsd_eth_drivers/libbsdport/libbsdport.h bsd_eth_drivers/libbsdport/libbsdport_api.h bsd_eth_drivers/libbsdport/libbsdport_post.h bsd_eth_drivers/libbsdport/miistuff.c bsd_eth_drivers/libbsdport/misc.c bsd_eth_drivers/libbsdport/mutex.h bsd_eth_drivers/libbsdport/rtems_callout.c bsd_eth_drivers/libbsdport/sysbus.c bsd_eth_drivers/libbsdport/taskqueue.h bsd_eth_drivers/links.am Cherrypick from freebsd_orig 2009-04-23 04:52:05 UTC Till Straumann ' - importing original 'releng_7_1' version of FXP driver from FreeBSD.': bsd_eth_drivers/if_fxp/if_fxpreg.h bsd_eth_drivers/if_fxp/rcvbundl.h Delete: INSTALL Makefile.am bootstrap config.h.in configure.ac m4/acinclude.m4 m4/config-if-present.m4 m4/cvstag.m4 m4/multilib-fix.m4 m4/multilib-installdir.m4 m4/rtems-bsp-postlink.m4 m4/rtems-bsplist.m4 m4/rtems-check-libargs.m4 m4/rtems-checkprog.m4 m4/rtems-checktool.m4 m4/rtems-checktop.m4 m4/rtems-fixup-prefix.m4 m4/rtems-isml.m4 m4/rtems-ismultibsp.m4 m4/rtems-isrtems.m4 m4/rtems-makevars.m4 m4/rtems-multilib.m4 m4/rtems-options.m4 m4/rtems-setup-recurse.m4 m4/rtems-tools.m4 m4/rtems-trim-builddir.m4 m4/rtems-verscheck.m4 makefile.top.am makefile.top.in rtems-pre.am rtems.am ssrlApps.components.in --- bsd_eth_drivers/libbsdport/.cvsignore | 1 + bsd_eth_drivers/libbsdport/Makefile.am | 27 +--- bsd_eth_drivers/libbsdport/alldrv.c | 30 ++++- bsd_eth_drivers/libbsdport/bus.h | 121 +++++++++++++++++- bsd_eth_drivers/libbsdport/callout.h | 44 ++++++- bsd_eth_drivers/libbsdport/devicet.c | 73 ++++++----- bsd_eth_drivers/libbsdport/ifmedia.c | 10 ++ bsd_eth_drivers/libbsdport/libbsdport.h | 50 +++++++- bsd_eth_drivers/libbsdport/libbsdport_api.h | 16 ++- bsd_eth_drivers/libbsdport/libbsdport_post.h | 35 +++++- bsd_eth_drivers/libbsdport/miistuff.c | 58 +++++++++ bsd_eth_drivers/libbsdport/misc.c | 179 +++++++++++++++++++++++++++ bsd_eth_drivers/libbsdport/mutex.h | 3 +- bsd_eth_drivers/libbsdport/rtems_callout.c | 31 ++++- bsd_eth_drivers/libbsdport/sysbus.c | 60 ++++++++- bsd_eth_drivers/libbsdport/taskqueue.h | 2 + 16 files changed, 664 insertions(+), 76 deletions(-) create mode 100644 bsd_eth_drivers/libbsdport/.cvsignore create mode 100644 bsd_eth_drivers/libbsdport/miistuff.c create mode 100644 bsd_eth_drivers/libbsdport/misc.c (limited to 'bsd_eth_drivers/libbsdport') diff --git a/bsd_eth_drivers/libbsdport/.cvsignore b/bsd_eth_drivers/libbsdport/.cvsignore new file mode 100644 index 0000000..70845e0 --- /dev/null +++ b/bsd_eth_drivers/libbsdport/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/bsd_eth_drivers/libbsdport/Makefile.am b/bsd_eth_drivers/libbsdport/Makefile.am index e6e31cd..06c70c8 100644 --- a/bsd_eth_drivers/libbsdport/Makefile.am +++ b/bsd_eth_drivers/libbsdport/Makefile.am @@ -5,7 +5,7 @@ include $(top_srcdir)/rtems-pre.am libbsdport_a_SOURCES = rtems_callout.c rtems_taskqueue.c rtems_udelay.c libbsdport_a_SOURCES += ifstuff.c devicet.c alldrv.c contigmalloc.c -libbsdport_a_SOURCES += sysbus.c malloc.c ifmedia.c +libbsdport_a_SOURCES += sysbus.c malloc.c ifmedia.c misc.c miistuff.c libbsdport_a_SOURCES += rtems_verscheck.h bus.h callout.h devicet.h libbsdport_a_SOURCES += libbsdport.h libbsdport_post.h mutex.h @@ -38,6 +38,9 @@ DUMMYHEADERS+=dummyheaders/netinet/ip6.h DUMMYHEADERS+=dummyheaders/vm/pmap.h DUMMYHEADERS+=dummyheaders/miibus_if.h +DUMMYHEADERS+=dummyheaders/miidevs.h +DUMMYHEADERS+=dummyheaders/dev/mii/brgphyreg.h + BUILT_SOURCES= include ../links.am @@ -48,25 +51,3 @@ include ../links.am # after OBJECTS are made :-( $(libbsdport_a_OBJECTS): $(DUMMYHEADERS) $(LINKS) -if FALSE -CLOBBER_ADDITIONS = -CLOBBER_ADDITIONS += $(srcdir)/dummyheaders -CLOBBER_ADDITIONS += $(addprefix $(srcdir)/,$(sort $(foreach n,$(LINKS),$(firstword $(subst /, ,$(n)))))) - -dummyheaders/%: - @if [ ! -d $(srcdir)/`dirname $@` ] ; then mkdir -p $(srcdir)/`dirname $@`; fi - @touch $(srcdir)/$@ - -# for each name listed in LINKS, create parent directories (if needed) -# and a symlink to file in . -# E.g., LINKS=a/b/c.h -# creates a/b/c.h -> ../../c.h -$(LINKS): - @if [ ! -d $(srcdir)/$(dir $@) ] ; then mkdir -p $(srcdir)/$(dir $@); fi - @ln -s `echo $@ | sed -e 's%[^/]\+[/]\+%../%g'` $(srcdir)/$@ - - -distclean-local: - $(RM) -r $(CLOBBER_ADDITIONS) -endif - diff --git a/bsd_eth_drivers/libbsdport/alldrv.c b/bsd_eth_drivers/libbsdport/alldrv.c index f81b95a..c68d6d1 100644 --- a/bsd_eth_drivers/libbsdport/alldrv.c +++ b/bsd_eth_drivers/libbsdport/alldrv.c @@ -1,14 +1,42 @@ #include #include "libbsdport_api.h" +#include "devicet.h" driver_t *libbsdport_netdriver_table_all[] = { &libbsdport_em_driver, &libbsdport_pcn_driver, &libbsdport_le_pci_driver, + &libbsdport_fxp_driver, + &libbsdport_bge_driver, + &libbsdport_re_driver, + &libbsdport_rl_driver, 0 }; -/* weak alias defaults to a table that includes all currently supported drivers */ +driver_t libbsdport_null_driver = {0}; + +extern driver_t libbsdport_em_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_pcn_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_le_pci_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_fxp_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_bge_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_re_driver + __attribute__((weak,alias("libbsdport_null_driver"))); +extern driver_t libbsdport_rl_driver + __attribute__((weak,alias("libbsdport_null_driver"))); + + +/* weak alias defaults to a table that includes + * all currently supported drivers. + * + * However, the individual entires are weak aliases + * themselves so that you don't have to link all drivers... + */ extern driver_t *libbsdport_netdriver_table [ sizeof(libbsdport_netdriver_table_all)/sizeof(libbsdport_netdriver_table_all[0]) diff --git a/bsd_eth_drivers/libbsdport/bus.h b/bsd_eth_drivers/libbsdport/bus.h index 19cb24f..e4a9d29 100644 --- a/bsd_eth_drivers/libbsdport/bus.h +++ b/bsd_eth_drivers/libbsdport/bus.h @@ -17,6 +17,12 @@ typedef enum { struct resource; +struct resource_spec { + int type; + int rid; + int flags; +}; + typedef bus_addr_t bus_space_handle_t; /* The 'bus_space_xxx()' inlines can be helped if the @@ -59,7 +65,6 @@ bus_space_write_##nwidth(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, *(volatile type __attribute__((may_alias)) *)(h+o) = v; \ }\ } - BUS_SPACE_DECL(u_int32_t, long, 4) BUS_SPACE_DECL(u_int16_t, word, 2) BUS_SPACE_DECL(u_int8_t, byte, 1) @@ -115,6 +120,8 @@ BUS_SPACE_DECL(u_int8_t, byte, 1, 8) #error "Missing definitions of bus_space_XXX() for this CPU architecture" #endif +#define bus_space_write_stream_4(_t, _h, _o, _v) \ + bus_space_write_4(_t, _h, _o, htole32(_v)) #undef BUS_SPACE_DECL @@ -140,10 +147,17 @@ BUS_SPACE_DECL(u_int8_t, byte, 1, 8) /* flags (1<<31) means unsupported */ #define RF_ACTIVE (1<<1) #define RF_SHAREABLE (1<<2) +#define RF_OPTIONAL (1<<3) struct resource * bus_alloc_resource_any(device_t dev, int type, int *prid, unsigned flags); +int +bus_alloc_resources(device_t dev, struct resource_spec *rs, struct resource **res); + +void +bus_release_resources(device_t dev, const struct resource_spec *rs, struct resource **res); + #define FILTER_STRAY 1 #define FILTER_HANDLED 0 @@ -157,6 +171,29 @@ bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filt #define INTR_MPSAFE 0 #define INTR_TYPE_NET 0 +/* + * INTR_FAST handlers are already more like 'filters', + * i.e., they disable interrupts and schedule work + * on a task queue. + * + * During porting the fast handler has to be slightly + * rewritten (must return an int value, FILTER_HANDLED + * if a valid IRQ was detected and work has been scheduled + * and FILTER_STRAY if this device didn't interrupt). + * + * You need to then remove INTR_FAST from the flags, + * pass the converted handler as the 'filter' argument + * and a NULL handler argument to bus_setup_intr(). + * + */ +extern int __INTR_FAST() __attribute__(( + error("\n\n==> you need to convert bus_setup_intr(INTR_FAST) to new API;\n" + " consult \n\n") +)); + +/* Barf at compile time if they try to use INTR_FAST */ +#define INTR_FAST (__INTR_FAST()) + int bus_teardown_intr(device_t dev, struct resource *r, void *cookiep); @@ -177,6 +214,37 @@ rman_get_bushandle(struct resource *r); bus_space_tag_t rman_get_bustag(struct resource *r); +/* Newer API (releng 7_1) */ +static inline u_int8_t bus_read_1(struct resource *r, bus_size_t o) +{ + return bus_space_read_1(rman_get_bustag(r), rman_get_bushandle(r), o); +} + +static inline u_int16_t bus_read_2(struct resource *r, bus_size_t o) +{ + return bus_space_read_2(rman_get_bustag(r), rman_get_bushandle(r), o); +} + +static inline u_int32_t bus_read_4(struct resource *r, bus_size_t o) +{ + return bus_space_read_4(rman_get_bustag(r), rman_get_bushandle(r), o); +} + +static inline void bus_write_1(struct resource *r, bus_size_t o, u_int8_t v) +{ + bus_space_write_1(rman_get_bustag(r), rman_get_bushandle(r), o, v); +} + +static inline void bus_write_2(struct resource *r, bus_size_t o, u_int16_t v) +{ + bus_space_write_2(rman_get_bustag(r), rman_get_bushandle(r), o, v); +} + +static inline void bus_write_4(struct resource *r, bus_size_t o, u_int32_t v) +{ + bus_space_write_4(rman_get_bustag(r), rman_get_bushandle(r), o, v); +} + #ifndef BUS_DMA_NOWAIT /* ignored anyways */ #define BUS_DMA_NOWAIT 0 @@ -192,6 +260,20 @@ rman_get_bustag(struct resource *r); #define BUS_DMA_COHERENT 0 #endif +#ifndef BUS_DMA_ZERO +/* ignored anyways */ +#define BUS_DMA_ZERO 0 +#endif + +#ifndef BUS_DMA_ALLOCNOW +/* ignored anyways */ +#define BUS_DMA_ALLOCNOW 0 +#endif + +#ifndef BUS_DMA_ZERO +#define BUS_DMA_ZERO 1 +#endif + /* unused */ #ifndef BUS_SPACE_MAXADDR #define BUS_SPACE_MAXADDR 0xdeadbeef @@ -223,6 +305,12 @@ typedef void *bus_dmamap_t; int bus_dma_tag_create(void *parent, unsigned alignment, unsigned bounds, uint32_t lowadd, uint32_t hiaddr, void (*filter)(void*), void *filterarg, unsigned maxsize, int nsegs, unsigned maxsegsize, unsigned flags, void (*lockfunc)(void*), void *lockarg, bus_dma_tag_t *ptag); +/* Dummy NULL fcn pointer */ +#define busdma_lock_mutex 0 + +extern uint32_t __busdma_dummy_Giant; +#define Giant __busdma_dummy_Giant + void bus_dma_tag_destroy(bus_dma_tag_t tag); @@ -265,10 +353,10 @@ bus_get_dma_tag(device_t dev) return 0; } -typedef void bus_dmamap_callback_t (void *, bus_dma_segment_t *, int, int); +typedef void bus_dmamap_callback_t (void *arg, bus_dma_segment_t *segs, int nseg, int error); static inline int -bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, caddr_t vaddr, bus_size_t size, void (*cb)(void *arg, bus_dma_segment_t *segs, int nseg, int error), void *arg, unsigned flags) +bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, void *vaddr, bus_size_t size, bus_dmamap_callback_t cb, void *arg, unsigned flags) { bus_dma_segment_t segs[1]; segs[0].ds_addr = CPU2BUSADDR(vaddr); @@ -277,6 +365,28 @@ bus_dma_segment_t segs[1]; return 0; } +typedef void bus_dmamap_callback2_t (void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t mapsize, int error); + +static inline int +bus_dmamap_load_mbuf(bus_dma_tag_t tag, bus_dmamap_t map, struct mbuf *m_head, bus_dmamap_callback2_t cb, void *arg, unsigned flags) +{ +/* hopefully there's enough stack ... */ +bus_dma_segment_t segs[tag->maxsegs]; +struct mbuf *m; +int n; +bus_size_t sz; + for ( m=m_head, sz=0, n=0; m; m=m->m_next, n++ ) { + if ( n >= tag->maxsegs ) { + cb(arg, segs, n, sz, EFBIG); + return EFBIG; + } + segs[n].ds_addr = CPU2BUSADDR(mtod(m, unsigned)); + sz += (segs[n].ds_len = m->m_len); + } + cb(arg, segs, n, sz, 0); + return 0; +} + #define bus_dmamap_unload(tag, map) do {} while (0) /* should we do something if we have no HW snooping ? */ @@ -285,4 +395,9 @@ bus_dma_segment_t segs[1]; #define bus_dmamap_create(tag, flags, pmap) ( *(pmap) = 0, 0 ) #define bus_dmamap_destroy(tag, map) do {} while (0) +int +resource_int_value(const char *name, int unit, const char *resname, int *result); +int +resource_long_value(const char *name, int unit, const char *resname, long *result); + #endif diff --git a/bsd_eth_drivers/libbsdport/callout.h b/bsd_eth_drivers/libbsdport/callout.h index 3f586bf..acc9de0 100644 --- a/bsd_eth_drivers/libbsdport/callout.h +++ b/bsd_eth_drivers/libbsdport/callout.h @@ -18,16 +18,56 @@ struct callout { void *c_arg; struct mtx *c_mtx; callout_time_t c_time; + unsigned c_flags; }; +#define CALLOUT_PENDING (1<<0) +#define CALLOUT_ACTIVE (1<<1) + +/* + * Strictly, we don't need any protection + * because the global network semaphore + * takes care; however we want to + */ +static inline int +callout_active(struct callout *p_c) +{ +int rval; +rtems_interrupt_level l; + rtems_interrupt_disable(l); + rval = p_c->c_flags & CALLOUT_ACTIVE; + rtems_interrupt_enable(l); + return rval; +} + +static inline int +callout_pending(struct callout *p_c) +{ +int rval; +rtems_interrupt_level l; + rtems_interrupt_disable(l); + rval = p_c->c_flags & CALLOUT_PENDING; + rtems_interrupt_enable(l); + return rval; +} + +static inline void +callout_decativate(struct callout *p_c) +{ +rtems_interrupt_level l; + rtems_interrupt_disable(l); + p_c->c_flags &= ~CALLOUT_ACTIVE; + rtems_interrupt_enable(l); +} + /* We cannot stop a callout that's in progress */ -void +int callout_stop(struct callout *c); #define callout_drain callout_stop -void +int callout_reset(struct callout *c, int ticks, void (*fn)(void*), void *arg); void diff --git a/bsd_eth_drivers/libbsdport/devicet.c b/bsd_eth_drivers/libbsdport/devicet.c index f197da4..fde3975 100644 --- a/bsd_eth_drivers/libbsdport/devicet.c +++ b/bsd_eth_drivers/libbsdport/devicet.c @@ -12,7 +12,8 @@ #include #include "libbsdport_api.h" -#undef DEBUG +#define DEBUG 0 +int libbsdportAttachVerbose = DEBUG; extern void real_libc_free(void*); @@ -65,11 +66,11 @@ devattach(device_t dev, int unit, struct rtems_bsdnet_ifconfig *cfg) { int error; -#ifdef DEBUG - printf("Now attaching %s%d: (0x%x:%x.%x)\n", - dev->name, unit, - dev->bushdr.pci.bus, dev->bushdr.pci.dev, dev->bushdr.pci.fun); -#endif + if ( libbsdportAttachVerbose ) { + printf("Now attaching %s%d: (0x%x:%x.%x)\n", + dev->name, unit, + dev->bushdr.pci.bus, dev->bushdr.pci.dev, dev->bushdr.pci.fun); + } dev->unit = unit; dev->ifconfig = cfg; @@ -247,6 +248,8 @@ device_t tmpdev; int error = 0; int bdfunit; +int n_bus; + if ( !attaching ) return ENOTSUP; @@ -256,20 +259,33 @@ int bdfunit; wantedunit |= 1<<31; nm[0]=0; } -#ifdef DEBUG - printf("Wanted unit is 0x%x, pattern '%s'\n", wantedunit, nm); + if ( libbsdportAttachVerbose ) + printf("Wanted unit is 0x%x, pattern '%s'\n", wantedunit, nm); + + n_bus = pci_bus_count(); +#ifdef __i386__ + /* ugliest of all hacks -- RTEMS routine is currently (4.9) + * still broken; it reports the (0-based) highest bus number + * instead of the count. + */ + n_bus++; #endif unit = 0; for ( i=0; (dr=libbsdport_netdriver_table[i]); i++ ) { + + /* unused slot ? */ + if ( 0 == dr->name && 0 == dr->methods ) + continue; + /* Find matching driver */ -#ifdef DEBUG - printf("Trying driver '%s' ...", dr->name); -#endif + if ( libbsdportAttachVerbose ) + printf("Trying driver '%s' ...", dr->name); + if ( matches(dr, nm) ) { -#ifdef DEBUG - printf("MATCH\n"); -#endif + + if ( libbsdportAttachVerbose ) + printf("MATCH\n"); assert( dr->methods ); @@ -281,7 +297,7 @@ int bdfunit; } dev = devalloc(dr); - for ( b=0; b>8, PCI_SLOT(bdfunit), PCI_FUNC(bdfunit)); -#endif + if ( libbsdportAttachVerbose ) { + printf("Probing PCI 0x%x:%x.%x\n", + bdfunit>>8, PCI_SLOT(bdfunit), PCI_FUNC(bdfunit)); + } /* has this device been attached already ? */ if ( (tmpdev = devattached(dev)) ) { @@ -319,9 +335,9 @@ int bdfunit; /* wanted unit == 0 means next avail. * unit is acceptable. */ -#ifdef DEBUG - printf("->SUCCESS\n"); -#endif + if ( libbsdportAttachVerbose ) + printf("->SUCCESS\n"); + if ( 0 == wantedunit || UNITMATCH(wantedunit, unit, bdfunit) ) { error = devattach(dev, thisunit, cfg); if ( !error ) @@ -331,9 +347,8 @@ int bdfunit; break; default: -#ifdef DEBUG - printf("->FAILED\n"); -#endif + if ( libbsdportAttachVerbose ) + printf("->FAILED\n"); /* probe failed */ break; } @@ -343,9 +358,11 @@ int bdfunit; } /* for all busses + slots */ devfree(dev); dev = 0; } /* matching driver */ -#ifdef DEBUG - else printf("NO MATCH\n"); -#endif + else + { + if ( libbsdportAttachVerbose ) + printf("NO MATCH\n"); + } } /* for all drivers */ /* Nothing found */ diff --git a/bsd_eth_drivers/libbsdport/ifmedia.c b/bsd_eth_drivers/libbsdport/ifmedia.c index 77c3bd3..dc85dfd 100644 --- a/bsd_eth_drivers/libbsdport/ifmedia.c +++ b/bsd_eth_drivers/libbsdport/ifmedia.c @@ -50,6 +50,16 @@ struct ifmedia_entry *ifmen, *ifmep, *ifme; } } +void +ifmedia_removeall(struct ifmedia *ifm) +{ +struct ifmedia_entry *ifmen, *ifmep; + for ( ifmep = LIST_FIRST(&ifm->ifm_list); ifmep; ifmep = ifmen ) { + ifmen = LIST_NEXT(ifmep, ifm_list); + free(ifmep, M_DEVBUF); + } +} + int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm, u_long cmd) { diff --git a/bsd_eth_drivers/libbsdport/libbsdport.h b/bsd_eth_drivers/libbsdport/libbsdport.h index 0fdd4a4..24d8da7 100644 --- a/bsd_eth_drivers/libbsdport/libbsdport.h +++ b/bsd_eth_drivers/libbsdport/libbsdport.h @@ -2,12 +2,19 @@ #define RTEMS_COMPAT_DEFS_H #include -#include +#ifndef _KERNEL #define _KERNEL +#endif +#ifndef __INSIDE_RTEMS_BSD_TCPIP_STACK__ +#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ +#endif + #include #include +#include + #include #include @@ -31,6 +38,10 @@ #include +#ifndef bswap32 +#define bswap32(_x) CPU_swap_u32(_x) +#endif + #if defined(__LITTLE_ENDIAN__) || defined(__i386__) static inline uint16_t htole16(uint16_t v) { return v; } static inline uint32_t htole32(uint32_t v) { return v; } @@ -128,6 +139,17 @@ static inline void membarrier_w() { asm volatile("eieio":::"memory"); } #error "Unknown CPU endianness" #endif +static __inline void +le32enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + #include #include @@ -175,6 +197,10 @@ static inline void membarrier_w() { asm volatile("eieio":::"memory"); } #define PCIR_POWER_STATUS 0x4 #endif +#ifndef PCIR_CACHELNSZ +#define PCIR_CACHELNSZ PCI_CACHE_LINE_SIZE +#endif + #ifndef PCIM_PSTAT_PME #define PCIM_PSTAT_PME 0x8000 #endif @@ -183,10 +209,17 @@ static inline void membarrier_w() { asm volatile("eieio":::"memory"); } #define PCIM_PSTAT_PMEENABLE 0x0100 #endif +#ifndef PCIM_CMD_MWRICEN +#define PCIM_CMD_MWRICEN PCI_COMMAND_INVALIDATE +#endif + #ifndef PCIY_PMG #define PCIY_PMG 0x01 #endif +#ifndef PCI_RF_DENSE +#define PCI_RF_DENSE 0 +#endif static inline uint32_t pci_read_config(device_t dev, unsigned reg, int width) @@ -259,6 +292,12 @@ pci_get_subdevice(device_t dev) return pci_read_config(dev, PCIR_SUBDEV_0, 2); } +static inline uint8_t +pci_get_revid(device_t dev) +{ + return pci_read_config(dev, PCIR_REVID, 1); +} + static inline void pci_enable_busmaster(device_t dev) { @@ -325,6 +364,9 @@ pci_release_msi(device_t dev) { } #define if_link_state_change(ifp, state) do {} while (0) +#define if_maddr_rlock(ifp) do {} while (0) +#define if_maddr_runlock(ifp) do {} while (0) + /* if_name should probably be const char * but isn't */ #define if_initname(ifp, name, unit) \ do { (ifp)->if_name = (char*)(name); (ifp)->if_unit = (unit); } while (0) @@ -362,12 +404,14 @@ contigfree(void *ptr, size_t size, int type); #define __FBSDID(x) #define MODULE_DEPEND(x1,x2,x3,x4,x5) -#define mii_mediachg(mii) do {} while (0) - void * real_libc_malloc(size_t); void real_libc_free(void*); +extern int libbsdport_bootverbose; +/* Try not to pollute global namespace */ +#define bootverbose libbsdport_bootverbose + #endif diff --git a/bsd_eth_drivers/libbsdport/libbsdport_api.h b/bsd_eth_drivers/libbsdport/libbsdport_api.h index 73b54b0..18e20ee 100644 --- a/bsd_eth_drivers/libbsdport/libbsdport_api.h +++ b/bsd_eth_drivers/libbsdport/libbsdport_api.h @@ -3,6 +3,7 @@ #include #include +#include /* $Id$ */ @@ -20,17 +21,30 @@ typedef struct driver driver_t; extern driver_t *libbsdport_netdriver_table[]; /* Drivers ported so far: */ + +/* Broadcom BCM57xx PCI */ +extern driver_t libbsdport_bge_driver; + /* Intel E1000 chips */ extern driver_t libbsdport_em_driver; + /* AMD 79C971..976 pcnet PCI */ extern driver_t libbsdport_pcn_driver; + +/* RealTek RTL8139C+, 8168, 8169, 8169S, 8110, 8101E, and 8111 PCI */ +extern driver_t libbsdport_re_driver; + +/* RealTek RTL8139 PCI */ +extern driver_t libbsdport_rl_driver; + /* AMD/Lance older (and later) chips; this driver also supports what 'pcn' * does but might not be as efficient. * NOTE: The 'le_pci' driver works with the pcnet32 (79C970A) emulation * of qemu. */ extern driver_t libbsdport_le_pci_driver; - +/* Intel E100 chips */ +extern driver_t libbsdport_fxp_driver; /* Generic driver attach function (can be used in rtems_bsdnet_ifconfig). * This routine selects a driver/device combination based on diff --git a/bsd_eth_drivers/libbsdport/libbsdport_post.h b/bsd_eth_drivers/libbsdport/libbsdport_post.h index fcf7e2d..ca3fe04 100644 --- a/bsd_eth_drivers/libbsdport/libbsdport_post.h +++ b/bsd_eth_drivers/libbsdport/libbsdport_post.h @@ -10,6 +10,8 @@ #undef SYSCTL_ADD_INT #define SYSCTL_ADD_INT(unused...) do { } while (0) + +#define RTEMS_SYSCTL_NOTYETSUP #endif #include @@ -22,9 +24,6 @@ #define IFF_DRV_RUNNING IFF_RUNNING #define IFF_DRV_OACTIVE IFF_OACTIVE -/* FIXME: should implement m_defrag() */ -#define m_defrag(m_headp, opt) NULL - static inline struct mbuf * m_getcl(int how, int type, unsigned flags) { @@ -87,9 +86,35 @@ ether_setaddr(struct ifnet *ifp, u_int8_t *eaddr); } while (0) #define ETHER_SIOCMULTIFRAG(e, c, ifr, ifp) \ - ( ENETRESET != (e = (SIOCADDMULTI == (c) ? \ + ( ((e) = (SIOCADDMULTI == (c) ? \ ether_addmulti((ifr), (struct arpcom*)(ifp)) : \ - ether_delmulti((ifr), (struct arpcom*)(ifp)) ))) \ + ether_delmulti((ifr), (struct arpcom*)(ifp)) )), \ + ((e) = ENETRESET == (e) ? 0 : (e)) ) #define arp_ifinit(ifp, ifa) arp_ifinit((struct arpcom *)ifp, ifa) + +#define mii_mediachg(mii) do {} while (0) + +/* find the currently active PHY; assume bootloader or firmware + * has set it up already. + * + * RETURNS: phy idx 0..31 or -1 on error + */ +int +rtems_mii_phy_probe(struct rtems_mdio_info *mdio, void *if_softc); + +/* + * Defragment a mbuf chain, returning the shortest possible + * chain of mbufs and clusters. If allocation fails and + * this cannot be completed, NULL will be returned, but + * the passed in chain will be unchanged. Upon success, + * the original chain will be freed, and the new chain + * will be returned. + * + * If a non-packet header is passed in, the original + * mbuf (chain?) will be returned unharmed. + */ +struct mbuf * +m_defrag(struct mbuf *m0, int how); + diff --git a/bsd_eth_drivers/libbsdport/miistuff.c b/bsd_eth_drivers/libbsdport/miistuff.c new file mode 100644 index 0000000..b15545f --- /dev/null +++ b/bsd_eth_drivers/libbsdport/miistuff.c @@ -0,0 +1,58 @@ +#include +#define _KERNEL +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define PHY_MAX 32 + +#undef DEBUG + +/* A helper to find the active PHY. We really should port + * the entire BSD miibus/phy support but that's a bigger + * project... + */ +int +rtems_mii_phy_probe(struct rtems_mdio_info *mdio, void *softc) +{ +int phy; +uint32_t bmsr, bmcr; + for ( phy = 0; phymdio_r(phy, softc, MII_BMSR, &bmsr) ) + continue; + + bmsr &= 0xffff; + + if ( 0 == bmsr || 0xffff == bmsr ) + continue; /* nothing here */ + + /* no media supported ? */ + if ( 0 == ((BMSR_EXTSTAT | 0xfe00) & bmsr ) ) + continue; /* probably nothing there */ + + if ( mdio->mdio_r(phy, softc, MII_BMCR, &bmcr) ) + continue; + + /* skip isolated or powered-down phys */ + if ( (BMCR_PDOWN | BMCR_ISO) & bmcr ) + continue; + +#ifdef DEBUG + printk("PHY #%u seems active; link status is %s\n", phy, BMSR_LINK & bmsr ? "UP" : "DOWN"); +#endif + + /* seems we found one */ + return phy; + } + + return -1; +} diff --git a/bsd_eth_drivers/libbsdport/misc.c b/bsd_eth_drivers/libbsdport/misc.c new file mode 100644 index 0000000..68e3c03 --- /dev/null +++ b/bsd_eth_drivers/libbsdport/misc.c @@ -0,0 +1,179 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +int libbsdport_bootverbose = 0; + +#ifdef WITNESS +#define MBUF_CHECKSLEEP(how) do {\ + if (how == M_WAITOK)\ + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,\ + "Sleeping in \"%s\"", __func__);\ + } while (0) +#else +#define MBUF_CHECKSLEEP(how) +#endif + +#define MBTOM(how)(how) + +u_int +m_length(struct mbuf *m0, struct mbuf **last) +{ + struct mbuf *m; + u_int len; + + len = 0; + for (m = m0; m != NULL; m = m->m_next) { + len += m->m_len; + if (m->m_next == NULL) + break; + } + if (last != NULL) + *last = m; + return (len); +} + +/* + * Duplicate "from"'s mbuf pkthdr in "to". + * "from" must have M_PKTHDR set, and "to" must be empty. + * In particular, this does a deep copy of the packet tags. + */ +int +m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how) +{ + + #if 0 + /* + * The mbuf allocator only initializes the pkthdr + * when the mbuf is allocated with MGETHDR. Many users + * (e.g. m_copy*, m_prepend) use MGET and then + * smash the pkthdr as needed causing these + * assertions to trip. For now just disable them. + */ + M_ASSERTPKTHDR(to); + /* Note: with MAC, this may not be a good assertion. */ + KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags), ("m_dup_pkthdr: to has tags")); + #endif + MBUF_CHECKSLEEP(how); + #ifdef MAC + if (to->m_flags & M_PKTHDR) + m_tag_delete_chain(to, NULL); + #endif + to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); + if ((to->m_flags & M_EXT) == 0) + to->m_data = to->m_pktdat; + to->m_pkthdr = from->m_pkthdr; + return 1; +} + +u_int +m_fixhdr(struct mbuf *m0) +{ + u_int len; + + len = m_length(m0, NULL); + m0->m_pkthdr.len = len; + return (len); +} + +/* + * Defragment a mbuf chain, returning the shortest possible + * chain of mbufs and clusters. If allocation fails and + * this cannot be completed, NULL will be returned, but + * the passed in chain will be unchanged. Upon success, + * the original chain will be freed, and the new chain + * will be returned. + * + * If a non-packet header is passed in, the original + * mbuf (chain?) will be returned unharmed. + */ +struct mbuf * +m_defrag(struct mbuf *m0, int how) +{ + struct mbuf *m_new = NULL, *m_final = NULL; + int progress = 0, length; + + MBUF_CHECKSLEEP(how); + if (!(m0->m_flags & M_PKTHDR)) + return (m0); + + m_fixhdr(m0); /* Needed sanity check */ + + #ifdef MBUF_STRESS_TEST + if (m_defragrandomfailures) { + int temp = arc4random() & 0xff; + if (temp == 0xba) + goto nospace; + } + #endif + + if (m0->m_pkthdr.len > MHLEN) + m_final = m_getcl(how, MT_DATA, M_PKTHDR); + else + m_final = m_gethdr(how, MT_DATA); + + if (m_final == NULL) + goto nospace; + + if (m_dup_pkthdr(m_final, m0, how) == 0) + goto nospace; + + m_new = m_final; + + while (progress < m0->m_pkthdr.len) { + length = m0->m_pkthdr.len - progress; + if (length > MCLBYTES) + length = MCLBYTES; + + if (m_new == NULL) { + if (length > MLEN) + m_new = m_getcl(how, MT_DATA, 0); + else + m_new = m_get(how, MT_DATA); + if (m_new == NULL) + goto nospace; + } + + m_copydata(m0, progress, length, mtod(m_new, caddr_t)); + progress += length; + m_new->m_len = length; + if (m_new != m_final) + m_cat(m_final, m_new); + m_new = NULL; + } + #ifdef MBUF_STRESS_TEST + if (m0->m_next == NULL) + m_defraguseless++; + #endif + m_freem(m0); + m0 = m_final; + #ifdef MBUF_STRESS_TEST + m_defragpackets++; + m_defragbytes += m0->m_pkthdr.len; + #endif + return (m0); + nospace: + #ifdef MBUF_STRESS_TEST + m_defragfailure++; + #endif + if (m_final) + m_freem(m_final); + return (NULL); +} + diff --git a/bsd_eth_drivers/libbsdport/mutex.h b/bsd_eth_drivers/libbsdport/mutex.h index 5476e37..8f0b5e6 100644 --- a/bsd_eth_drivers/libbsdport/mutex.h +++ b/bsd_eth_drivers/libbsdport/mutex.h @@ -46,7 +46,8 @@ mtx_destroy(struct mtx *m) } /* what ? */ -#define MA_OWNED 1 +#define MA_OWNED 1 +#define MA_NOTOWNED 0 static inline void mtx_assert(struct mtx *m, int what) { diff --git a/bsd_eth_drivers/libbsdport/rtems_callout.c b/bsd_eth_drivers/libbsdport/rtems_callout.c index ce9a477..c041c5b 100644 --- a/bsd_eth_drivers/libbsdport/rtems_callout.c +++ b/bsd_eth_drivers/libbsdport/rtems_callout.c @@ -100,6 +100,9 @@ LIST_KEY_DECL(k); n = c->c_next; if ( c->c_time <= 0 ) { /* this one expired */ + rtems_interrupt_disable(k1); + c->c_flags &= ~ CALLOUT_PENDING; + rtems_interrupt_enable(k1); c_deq(c); if ( c->c_func ) c->c_func(c->c_arg); @@ -173,31 +176,43 @@ bail: /* We cannot stop a callout that's in progress */ -void +int callout_stop(struct callout *c) { +rtems_interrupt_level l; LIST_KEY_DECL(k); if ( !c->c_pprev ) - return; /* not currently on a list */ + return 0; /* not currently on a list */ LIST_LOCK(k); + /* have to check again */ + if ( ! c->c_pprev ) { + LIST_UNLOCK(k); + return 0; + } /* remove from list */ c_deq(c); + rtems_interrupt_disable(l); + c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING); + rtems_interrupt_enable(l); LIST_UNLOCK(k); + + return 1; } -void +int callout_reset(struct callout *c, int ticks, timeout_t fn, void *arg) { +rtems_interrupt_level l; LIST_KEY_DECL(k); -int i; +int i, rval; if ( ticks <= 0 ) ticks = 1; - callout_stop(c); + rval = callout_stop(c); c->c_func = fn; c->c_arg = arg; @@ -209,7 +224,13 @@ int i; /* enqueue */ c_enq(&c_wheel[i], c); + rtems_interrupt_disable(l); + c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING); + rtems_interrupt_enable(l); + LIST_UNLOCK(k); + + return rval; } static rtems_id callout_tid = 0; diff --git a/bsd_eth_drivers/libbsdport/sysbus.c b/bsd_eth_drivers/libbsdport/sysbus.c index fcd3aac..a88d7ad 100644 --- a/bsd_eth_drivers/libbsdport/sysbus.c +++ b/bsd_eth_drivers/libbsdport/sysbus.c @@ -96,6 +96,41 @@ int isio; return (struct resource*)0; } +int +bus_alloc_resources(device_t dev, struct resource_spec *rs, + struct resource **res) +{ + int i; + + for (i = 0; rs[i].type != -1; i++) + res[i] = NULL; + for (i = 0; rs[i].type != -1; i++) { + res[i] = bus_alloc_resource_any(dev, + rs[i].type, &rs[i].rid, rs[i].flags); + if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) { + bus_release_resources(dev, rs, res); + return (ENXIO); + } + } + return (0); +} + +void +bus_release_resources(device_t dev, const struct resource_spec *rs, + struct resource **res) +{ + int i; + + for (i = 0; rs[i].type != -1; i++) + if (res[i] != NULL) { + bus_release_resource( + dev, rs[i].type, rs[i].rid, res[i]); + res[i] = NULL; + } +} + + + struct irq_cookie { device_t dev; driver_filter_t handler; @@ -143,8 +178,6 @@ bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filt int rval; struct irq_cookie *info = 0; - - if ( filter && handler ) { rtems_panic("bus_setup_intr for both: filter & handler not implemented\n"); } @@ -154,7 +187,7 @@ struct irq_cookie *info = 0; device_printf(dev, "bus_setup_intr: device has no driver attached\n"); return EINVAL; } else if ( !dev->drv->methods->irq_check_dis ) { - device_printf(dev, "bus_setup_intr: driver has no 'irq_dis' method\n"); + device_printf(dev, "bus_setup_intr: driver has no 'irq_check_dis' method\n"); return EINVAL; } } @@ -247,10 +280,13 @@ int bus_dmamem_alloc(bus_dma_tag_t tag, void **p_vaddr, unsigned flags, bus_dmamap_t *p_map) { uintptr_t a; - if ( ! (*p_map = malloc(tag->maxsize + tag->alignment, M_DEVBUF, M_NOWAIT)) ) +unsigned sz = tag->maxsize + tag->alignment; + if ( ! (*p_map = malloc(sz, M_DEVBUF, M_NOWAIT)) ) return ENOMEM; a = ((uintptr_t)*p_map + tag->alignment - 1 ) & ~(tag->alignment - 1); *p_vaddr = (void*)a; + if ( (BUS_DMA_ZERO & flags) ) + memset(*p_map, 0, sz); return 0; } @@ -259,3 +295,19 @@ bus_dmamem_free(bus_dma_tag_t tag, void *vaddr, bus_dmamap_t map) { free(map, M_DEVBUF); } + +/* Dummy handle for Giant mutex */ +uint32_t __busdma_dummy_Giant = 0; + +int +resource_int_value(const char *name, int unit, const char *resname, int *result) +{ + /* not implemented */ + return ENOENT; +} +int +resource_long_value(const char *name, int unit, const char *resname, long *result) +{ + /* not implemented */ + return ENOENT; +} diff --git a/bsd_eth_drivers/libbsdport/taskqueue.h b/bsd_eth_drivers/libbsdport/taskqueue.h index a341ec1..d700edf 100644 --- a/bsd_eth_drivers/libbsdport/taskqueue.h +++ b/bsd_eth_drivers/libbsdport/taskqueue.h @@ -31,6 +31,8 @@ taskqueue_create_fast(const char *name, int mflags, tq_enq_fn, void *ctxt); int taskqueue_enqueue(struct taskqueue *tq, struct task *ta); +#define taskqueue_enqueue_fast(_q,_t) taskqueue_enqueue(_q,_t) + void taskqueue_thread_enqueue(void *ctxt); -- cgit v1.2.3