public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
From: "ariga masahiro" <ariga@link-lab.co.jp>
To: "Andrew Lunn" <andrew@lunn.ch>
Cc: <ecos-discuss@ecos.sourceware.org>
Subject: [ECOS] Not working lan91cxx_sc drv
Date: Mon, 01 Oct 2007 05:01:00 -0000	[thread overview]
Message-ID: <000301c803e7$fd728a50$1c0110ac@ariga> (raw)
In-Reply-To: <001501c801b7$2de8bed0$1c0110ac@ariga>

Hi,

I am the same person who posted "Question about interrupt trigger 
mode",dated 9/28/2007
but since then I am encountered the most serious problem so I change title 
and post this
most-urgent,most-ernest and most-desperate mail.

As I said,
My target uses SMSC LAN91C111 chip,CPU is SH7709S.
As ethernet interrupt,uses IRQ3 line.
I build "net" template,eCos source is updated by CVS checkout.

As I inserted LAN91C111's mask routine in the ISR,
I succeeded to entered into DSR.
(This interrupt was caused not by eCos-proper code, but by my tampered
routine.I will later explain.)
But although RCV-INT is assserted,delivering-packet routine never called,
so I entered repetedly ISR and DSR.
Then I discovered LAN91C111 driver's receive routine was never called.

Please forgive me long mail,but I try to
inform you as correctly as possible.
First I relate current problem,and later describe what I have tampered with.

I register SMSC interrupt ruoitne
in \packages\devs\eth\smsc\lan91cxx\current\src\if_lan91cxx.c's
smsc_lan91cxx_init(struct cyg_netdevtab_entry *tab)
like this,
#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
    // Initialize environment, setup interrupt handler
    cyg_drv_interrupt_create(cpd->interrupt,
                             CYGNUM_DEVS_ETH_SMSC_LAN91CXX_INT_PRIO,
                             (cyg_addrword_t)sc, //  Data item passed to 
interrupt handler
                             (cyg_ISR_t *)lan91cxx_isr,
                             (cyg_DSR_t *)eth_drv_dsr, // The logical driver 
DSR
                             &lan91cxx_interrupt_handle,
                             &lan91cxx_interrupt);
    cyg_drv_interrupt_attach(lan91cxx_interrupt_handle);
#endif // !CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
    cyg_drv_interrupt_acknowledge(cpd->interrupt);
    cyg_drv_interrupt_unmask(cpd->interrupt);

And register LAN91C111 driver in my target's 
\packages\devs\eth\sh\inserter\current\include\devs_eth_inserter.inl.
I think this is important so I put on all content.
#include <pkgconf/system.h>
#include <pkgconf/devs_eth_sh_inserter.h>
#include <cyg/hal/hal_intr.h>

// MAC address is stored as a Redboot config option
#ifdef CYGPKG_REDBOOT
#include <pkgconf/redboot.h>
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
#include <redboot.h>
#include <flash_config.h>

#define LAN91CXX_IS_LAN91C111

RedBoot_config_option("Network hardware address [MAC]",
                      inserter_esa,
                      ALWAYS_ENABLED, true,
                      CONFIG_ESA, 0
    );
#endif
#endif

// ESA address fetch function
static void inserter_get_ESA(struct lan91cxx_priv_data *cpd)
{
    // Fetch hardware address from RedBoot config
#if defined(CYGSEM_DEVS_ETH_SH_INSERTER_REDBOOT_ESA)
#if defined(CYGPKG_REDBOOT) && \
    defined(CYGSEM_REDBOOT_FLASH_CONFIG)
    flash_get_config("inserter_esa", cpd->enaddr, CONFIG_ESA);
#else
#error "No RedBoot flash configuration to store ESA"
#endif
#else
    unsigned char static_esa[] = CYGDAT_DEVS_ETH_SH_INSERTER_ESA;
    memcpy(cpd->enaddr, static_esa, 6);
#endif
}

static lan91cxx_priv_data lan91cxx_eth0_priv_data = {
    config_enaddr : inserter_get_ESA,
#ifndef CYGSEM_DEVS_ETH_SH_INSERTER_REDBOOT_ESA
    enaddr: CYGDAT_DEVS_ETH_SH_INSERTER_ESA,
    hardwired_esa : true,
#else
    hardwired_esa : false,
#endif

#if 0
   base : (unsigned short *) SA1110_FHH_ETH_IOBASE,
   attbase : (unsigned char *) SA1110_FHH_ETH_MMBASE,
   interrupt : SA1110_IRQ_GPIO_ETH
#else
   base : (unsigned short *) 0xa8000000,
   interrupt : 9,
#endif
};

ETH_DRV_SC(lan91cxx_sc,
           &lan91cxx_eth0_priv_data,          // Driver specific data
           CYGDAT_DEVS_ETH_SH_INSERTER_NAME, // Name for device
           lan91cxx_start,
           lan91cxx_stop,
           lan91cxx_control,
           lan91cxx_can_send,
           lan91cxx_send,
           lan91cxx_recv,
           lan91cxx_deliver,
           lan91cxx_poll,
           lan91cxx_int_vector
);

NETDEVTAB_ENTRY(lan91cxx_netdev,
                "lan91cxx_" CYGDAT_DEVS_ETH_SH_INSERTER_NAME,
                smsc_lan91cxx_init,
                &lan91cxx_sc);

//EOF devs_eth_inserter.inl

I found ETH_DRV_SC definition as below.
\packages\io\eth\current\include\eth_drv.h
#define 
ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv,deliver,poll,int_vector) 
\
static void start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags); 
\
static void stop(struct eth_drv_sc *sc); \
static int  control(struct eth_drv_sc *sc, unsigned long key, void *data, 
int data_length); \
static int  can_send(struct eth_drv_sc *sc); \
static void send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int 
sg_len, int total, unsigned long key); \
static void recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int 
sg_len); \
static void deliver(struct eth_drv_sc *sc); \
static void poll(struct eth_drv_sc *sc); \
static int  int_vector(struct eth_drv_sc *sc); \
static struct eth_hwr_funs sc##_funs = {        \
    start,                                      \
    stop,                                       \
    control,                                    \
    can_send,                                   \
    send,                                       \
    recv,                                       \
    deliver,                                    \
    poll,                                       \
    int_vector,                                 \
    &eth_drv_funs,                              \
    (struct eth_drv_funs *)0 };                 \
struct eth_drv_sc sc = {&sc##_funs, priv, name};

I assume this is developed like below,
#define 
ETH_DRV_SC(lan91cxx_sc,&lan91cxx_eth0_priv_data,CYGDAT_DEVS_ETH_SH_INSERTER_NAME,lan91cxx_start,lan91cxx_stop,lan91cxx_control,lan91cxx_can_send,lan91cxx_send,lan91cxx_recv,lan91cxx_deliver,lan91cxx_poll,lan91cxx_int_vector) 
\
static void lan91cxx_start(struct eth_drv_sc *lan91cxx_sc, unsigned char 
*enaddr, int flags); \
static void lan91cxx_stop(struct eth_drv_sc *lan91cxx_sc); \
static int  lan91cxx_control(struct eth_drv_sc *lan91cxx_sc, unsigned long 
key, void *data, int data_length); \
static int  lan91cxx_can_send(struct eth_drv_sc *lan91cxx_sc); \
static void lan91cxx_send(struct eth_drv_sc *lan91cxx_sc, struct eth_drv_sg 
*sg_list, int sg_len, int total, unsigned long key); \
static void lan91cxx_recv(struct eth_drv_sc *lan91cxx_sc, struct eth_drv_sg 
*sg_list, int sg_len); \
static void lan91cxx_deliver(struct eth_drv_sc *lan91cxx_sc); \
static void lan91cxx_pollpoll(struct eth_drv_sc *lan91cxx_sc); \
static int  lan91cxx_int_vector(struct eth_drv_sc *lan91cxx_sc); \
static struct eth_hwr_funs lan91cxx_sc_funs = {        \
    lan91cxx_start,                                      \
    lan91cxx_stop,                                       \
    lan91cxx_control,                                    \
    lan91cxx_can_send,                                   \
    lan91cxx_send,                                       \
    lan91cxx_recv,                                       \
    lan91cxx_deliver,                                    \
    lan91cxx_poll,                                       \
    lan91cxx_int_vector,                                 \
    &eth_drv_funs,                              \
    (struct eth_drv_funs *)0 };                 \
struct eth_drv_sc lan91cxx_sc = {&lan91cxx_sc_funs, 
&lan91cxx_eth0_priv_data, CYGDAT_DEVS_ETH_SH_INSERTER_NAME};

I assume lan91cxx_recv must be called to operate on packets,
but it was never called.

I traced DSR routine
DSR is this
\packages\io\eth\current\src\net\eth_drv.c
void
eth_drv_dsr(cyg_vector_t vector,
            cyg_ucount32 count,
            cyg_addrword_t data)
{
    struct eth_drv_sc *sc = (struct eth_drv_sc *)data;

#ifdef CYGDBG_USE_ASSERTS
    // then check that this really is a "sc"
    {
        cyg_netdevtab_entry_t *t;
        for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++)
            if ( ((struct eth_drv_sc *)t->device_instance) == sc )
                break; // found it
        CYG_ASSERT( t != &__NETDEVTAB_END__, "eth_drv_dsr: Failed to find sc 
in NETDEVTAB" );
    }
#endif // Checking code

    sc->state |= ETH_DRV_NEEDS_DELIVERY;

    ecos_synch_eth_drv_dsr(); // [request] run delivery function for this 
dev
}

And in \packages\net\bsd_tcpip\current\src\ecos\timeout.c
void ecos_synch_eth_drv_dsr(void)
{
    cyg_flag_setbits( &alarm_flag, 2 );
}

And in \packages\kernel\current\src\common\kapi.cxx
void cyg_flag_setbits( cyg_flag_t *flag, cyg_flag_value_t value) __THROW
{
    ((Cyg_Flag *)flag)->setbits( value );
}

And in \packages\kernel\current\src\sync\flag.cxx
void
Cyg_Flag::setbits( Cyg_FlagValue arg )
{
    CYG_REPORT_FUNCTION();
    CYG_ASSERTCLASS( this, "Bad this pointer");

    // Prevent preemption
    Cyg_Scheduler::lock();

    // OR in the argument to get a new flag value.
    value |= arg;

    // anyone waiting?
    if ( !(queue.empty()) ) {
        FlagWaitInfo   *p;
        Cyg_Thread     *thread;
        Cyg_ThreadQueue holding;

        do {
            thread = queue.dequeue();
            p = (FlagWaitInfo *)(thread->get_wait_info());

            CYG_ASSERT( (p->allmask == 0) != (p->anymask == 0),
                        "Both masks set" );
            CYG_ASSERT( 0 == p->value_out, "Thread already awoken?" );

            if ( ((p->allmask != 0) && (p->allmask & value) == p->allmask) 
||
                 ((p->anymask & value) != 0 ) ) {
                // success!  awaken the thread
                thread->set_wake_reason( Cyg_Thread::DONE );
                thread->wake();
                // return the successful value to it
                p->value_out = value;
                // do we clear the value; is this the end?
                if ( p->do_clear ) {
                    // we can break here but need to preserve ordering
                    value = 0;
                    // so let it cycle the whole queue regardless
                }
            }
            else {
                // preserve the entry on the holding queue
                holding.enqueue( thread );
            }
        } while ( !(queue.empty()) );

        // Now re-queue the unaffected threads back into the flag queue
        while ( !(holding.empty()) ) {
            queue.enqueue( holding.dequeue() );
        }
    }
    // Unlock scheduler and allow other threads to run
    Cyg_Scheduler::unlock();
    CYG_REPORT_RETURN();
}

Truely,I cannot fathom this coding and
I would appreciate if you kindly teach me how lan91cxx_recv is to be called.

Now I describe what I have tampered with in detail,please forgive me lengthy 
details.
The beginning of the matter is when I ran eCos as it is,I couldn't make 
LAN91C111 into LINK State,
LINK LED didn't light.So I inserted my own routine in order to operate 
LAN91C111 into LINK State in top of
\packages\io\eth\current\src\net\eth_drv.c's eth_drv_init function like 
below.
eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
{
    // this is my tampered coding
    cyg_netdevtab_entry_t *t;

    struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#ifdef CYGPKG_NET_FREEBSD_STACK
    int unit;
    char *np, *xp;
#endif

    // this is my tampered coding
    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
        log(LOG_INIT, "Init device '%s'\n", t->name);
        if (smsc_91c111_init(t)) {             // this is my concocted 
routine
            t->status = CYG_NETDEVTAB_STATUS_AVAIL;
        } else {
            // What to do if device init fails?
            t->status = 0;  // Device not [currently] available
        }
    }

and in order making LAN91C111 into LINK State it was necessary to use 
interrupt so I enabled LAN91C111 interrupt in my concocted routine.
Above-mentioned interrupt was caused by my tampered code.At LINK-established 
time interrupt happened.

On second thought, I realized my tampering was wrong.
So I quitted my tampering routine, I returned to eCos original source and 
checked why couldn't make LINK LED lighed.
I discovered it never called lan91cxx routines(i.e. ETH_DRV_SC routines).

Below is RedBoot output messages log.
I breaked lan91cxx_start() but never entered it.
I made DEBUG_FUNCTION() available.
-- RedBoot output messages log
My Flash ID is 4:22f9:0:19
eth_drv_init:enaddr=0x8c0005c4
Ethernet eth0: MAC address 00:40:31:08:01:00
IP: 172.16.1.200/255.255.255.0, Gateway: 172.16.1.1
Default server: 172.16.1.1

RedBoot(tm) bootstrap and debug environment [ROM]
Non-certified release, version UNKNOWN - built 16:50:29, Sep 19 2007

Platform: inserter (SH 7709S)
Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
Copyright (C) 2003, 2004, 2005, 2006 eCosCentric Limited

RAM: 0x8c000000-0x90000000, [0x8c00bed0-0x8ffed000] available
FLASH: 0xa0000000 - 0xa0400000, 64 blocks of 0x00010000 bytes each.
== Executing boot script in 3.000 seconds - enter ^C to abort
RedBoot> fis load -b 0x8c010000 nc_slave
RedBoot> channel 1
RedBoot> go 0x8c010000
Network stack using 69632 bytes for misc space
                    69632 bytes for mbufs
                    139264 bytes for mbuf clusters
[cyg_net_init] Init: mbinit(0x00000000)
[cyg_net_init] Init: cyg_net_init_devs(0x00000000)
Init device 'lan91cxx_eth0'
smsc_lan91cxx_init
LAN91CXX - supposed BankReg @ a800000e = 3302
LAN91CXX - type: 9, rev: 1
LAN91CXX - status: 0069
LAN91CXX - static ESA: 00:40:31:08:01:00
[cyg_net_init] Init: loopattach(0x00000000)
[cyg_net_init] Init: ifinit(0x00000000)
[cyg_net_init] Init: domaininit(0x00000000)
[cyg_net_init] Init: cyg_net_add_domain(0x8c05a7b4)
New domain internet at 0x00000000
[cyg_net_init] Init: cyg_net_add_domain(0x8c05a1f8)
New domain route at 0x00000000
[cyg_net_init] Init: call_route_init(0x00000000)
[cyg_net_init] Done
Start Network Characterization - SLAVE
No load = 58470
Set background load = 20%
Set background load = 0%
High Load[20] = 37131 => 37%
Set background load = 20%
Set background load = 0%
Load[10] = 47736 => 19%
Set background load = 20%
Set background load = 0%
Final load[10] = 47853 => 19%
Start test for eth0
-- end of RedBoot output messages log

All matters considered,I deduce that ETH_DRV_SC-table-reference-functions 
are not working.
I cannot understand where and how they are called.
Please teach me how to correctly call these functions.

Particularly I am curious to know eCos's system contrivance for calling drv 
routines
and if you know anything(e.g. web site,etc.) to guide me, please enlighten 
me.
I am "a drowning man catching at a straw".

I admit my knowledge is below than ecos level,
but my company's expecting in applying eCos into products.
And I trust eCos, so please do not let me down
and I eanestly beseech your kind advice.

Masahiro Ariga


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

  reply	other threads:[~2007-10-01  5:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-28 10:06 [ECOS] Question about interrupt trigger mode ariga masahiro
2007-10-01  5:01 ` ariga masahiro [this message]
2007-10-02  1:18   ` [ECOS] Not working lan91cxx_sc drv ariga masahiro
2007-10-02  4:46     ` ariga masahiro
2007-10-02  5:27       ` ariga masahiro
2007-10-02  7:08         ` ariga masahiro
2007-10-02 10:45           ` ariga masahiro
2007-10-11  9:01           ` [ECOS] Not enter VSR routine when lan91cxx_start executed ariga masahiro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='000301c803e7$fd728a50$1c0110ac@ariga' \
    --to=ariga@link-lab.co.jp \
    --cc=andrew@lunn.ch \
    --cc=ecos-discuss@ecos.sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).