Jan,

Thanks for such a quick response! We've made good progress with 
the RTnet Arcnet driver but have a few questions about code which 
doesn't quite match up to the existing examples.

And I have little experience with designing network drivers (or 
any driver!) .. therefore the questions might seem basic.

1.) The original arcnet driver does not call alloc_etherdev but 
rather alloc_netdev (shown below). Can I still change this 
function call like suggested in your porting documenation? What 
effect will this have on the program?

BEFORE

struct net_device *alloc_arcdev(char *name)
{
        struct net_device *dev;

        dev = alloc_netdev(sizeof(struct arcnet_local),
                           name && *name ? name : "arc%d", arcdev_setup);
        if(dev) {
                struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
                spin_lock_init(&lp->lock);
        }

        return dev;
}

AFTER

struct rtnet_device *alloc_arcdev(char *name)
{
        struct rtnet_device *dev;

        /*** RTnet ***/
        dev = rt_alloc_etherdev(sizeof(struct arcnet_local)); // 
etherdev?
        
        rtdev_alloc_name(dev, "rtarc%d");
        rt_rtdev_connect(dev, &RTDEV_manager);
        RTNET_SET_MODULE_OWNER(dev);
        dev->vers = RTDEV_VERS_2_0;
        /*** RTnet ***/

        if(dev) {
                struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
                rtdm_lock_init(&lp->lock); /*** RTnet ***/
        }

        return dev;
}

2.) In your example, you initialize the skb_pool in the probe 
function and if the return value is less than twice the ring size 
then you release the skb_pool and call a few 'cleanup' functions.

e.g.     pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, 
lp->dma_addr);

    I'm not sure how it works, but I cannot this function because 
the struct arcnet_local does not have a field called 'dma_addr'. 
So my question is .. is dma_addr disguised under another name in 
the arcnet_local struct? and if not do I even need to call this 
function?

static int __devinit com20020pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
{
        struct rtnet_device *dev;
        struct arcnet_local *lp;
        int ioaddr, err;

        /*** RTnet ***/
        
        cards_found++;
        if (cards[cards_found] == 0)
        return -ENODEV;

        /*** RTnet ***/
        
        if (pci_enable_device(pdev))
                return -EIO;
        dev = alloc_arcdev(device);
        if (!dev)
                return -ENOMEM;
        lp = dev->priv;

        pci_set_drvdata(pdev, dev);

        // SOHARD needs PCI base addr 4
        if (pdev->vendor==0x10B5) {
                BUGMSG(D_NORMAL, "SOHARD\n");
                ioaddr = pci_resource_start(pdev, 4);
        }
        else {
                BUGMSG(D_NORMAL, "Contemporary Controls\n");
                ioaddr = pci_resource_start(pdev, 2);
        }

        if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) 
{
                BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n",
                       ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
                err = -EBUSY;
                goto out_dev;
        }

        /*** RTnet ***/
        if (rtskb_pool_init(&lp->skb_pool, RX_RING_SIZE*2) < 
RX_RING_SIZE*2) {
                rtskb_pool_release(&lp->skb_pool);
--------->   // pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, 
lp->dma_addr);
                release_region(ioaddr, ARCNET_TOTAL_SIZE);
                rtdev_free(dev);
        return -ENOMEM;
        }
        /*** RTnet ***/

        // Dummy access after Reset
        // ARCNET controller needs this access to detect bustype
        outb(0x00,ioaddr+1);
        inb(ioaddr+1);

        dev->base_addr = ioaddr;
        dev->irq = pdev->irq;
        dev->dev_addr[0] = node;
        lp->card_name = "PCI COM20020";
        lp->card_flags = id->driver_data;
        lp->backplane = backplane;
        lp->clockp = clockp & 7;
        lp->clockm = clockm & 3;
        lp->timeout = timeout;
        lp->hw.owner = THIS_MODULE;

        if (ASTATUS() == 0xFF) {
                BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
                       "but seems empty!\n", ioaddr);
                err = -EIO;
                goto out_port;
        }
        
        if (com20020_check(dev)) {
                err = -EIO;
                goto out_port;
        }

        if ((err = com20020_found(dev, SA_SHIRQ)) != 0)
                goto out_port;

        return 0;

out_port:
        release_region(ioaddr, ARCNET_TOTAL_SIZE);
out_dev:
        rtdev_free(dev);
        return err;
}

     here's a snapshot of the arcnet_local struct ...

struct arcnet_local {
        struct net_device_stats stats;

        uint8_t config,         /* current value of CONFIG register */
                timeout,        /* Extended timeout for COM20020 */
                backplane,      /* Backplane flag for COM20020 */
                clockp,         /* COM20020 clock divider */
                clockm,         /* COM20020 clock multiplier flag */
                setup,          /* Contents of setup1 register */
                setup2,         /* Contents of setup2 register */
                intmask;        /* current value of INTMASK register */
        uint8_t default_proto[256];     /* default encap to use for each host 
*/
        int     cur_tx,         /* buffer used by current transmit, or -1 */
                next_tx,        /* buffer where a packet is ready to send */
                cur_rx;         /* current receive buffer */
        int     lastload_dest,  /* can last loaded packet be acked? */
                lasttrans_dest; /* can last TX'd packet be acked? */
        int     timed_out;      /* need to process TX timeout and drop packet */
        unsigned long last_timeout;     /* time of last reported timeout */
        char *card_name;        /* card ident string */
        int card_flags;         /* special card features */

        /*** RTnet ***/

        struct rtskb *tx_skbuff[TX_RING_SIZE];
        struct rtskb *rx_skbuff[RX_RING_SIZE];
        struct rtskb_queue skb_pool;

        rtdm_irq_t irq_handle;

        /*** RTnet ***/

        /* On preemtive and SMB a lock is needed */

        rtdm_lock_t lock;

        /*
         * Buffer management: an ARCnet card has 4 x 512-byte buffers, 
each of
         * which can be used for either sending or receiving.  The new 
dynamic
         * buffer management routines use a simple circular queue of 
available
         * buffers, and take them as they're needed.  This way, we 
simplify
         * situations in which we (for example) want to pre-load a 
transmit
         * buffer, or start receiving while we copy a received packet to
         * memory.
         *
         * The rules: only the interrupt handler is allowed to _add_ 
buffers to
         * the queue; thus, this doesn't require a lock.  Both the 
interrupt
         * handler and the transmit function will want to _remove_ 
buffers, so
         * we need to handle the situation where they try to do it at the 
same
         * time.
         *
         * If next_buf == first_free_buf, the queue is empty.  Since 
there are
         * only four possible buffers, the queue should never be full.
         */
        atomic_t buf_lock;
        int buf_queue[5];
        int next_buf, first_free_buf;

        /* network "reconfiguration" handling */
        time_t first_recon,             /* time of "first" RECON message to 
count 
*/
                last_recon;             /* time of most recent RECON */
        int num_recons;         /* number of RECONs between first and last. */
        bool network_down;              /* do we think the network is down? */

        bool excnak_pending;    /* We just got an excesive nak interrupt */

        struct {
                uint16_t sequence;      /* sequence number (incs with each 
packet) 
*/
                uint16_t aborted_seq;

                struct Incoming incoming[256];  /* one from each address */
        } rfc1201;

        /* really only used by rfc1201, but we'll pretend it's not */
        struct Outgoing outgoing;       /* packet currently being sent */

        /* hardware-specific functions */
        struct {
                struct module *owner;
                void (*command) (struct rtnet_device * dev, int cmd);
                int (*status) (struct rtnet_device * dev);
                void (*intmask) (struct rtnet_device * dev, int mask);
                bool (*reset) (struct rtnet_device * dev, bool really_reset);
                void (*open) (struct rtnet_device * dev);
                void (*close) (struct rtnet_device * dev);

                void (*copy_to_card) (struct rtnet_device * dev, int bufnum, 
int 
offset,
                                      void *buf, int count);
                void (*copy_from_card) (struct rtnet_device * dev, int bufnum, 
int offset,
                                        void *buf, int count);
        } hw;

        void __iomem *mem_start;        /* pointer to ioremap'ed MMIO */
};

     and if you're curious com20020_found looks like this ...

/* Set up the struct rtnet_device associated with this card.  
Called after
 * probing succeeds.
 */
int com20020_found(struct rtnet_device *dev, int shared)
{
        struct arcnet_local *lp;
        int ioaddr = dev->base_addr;
        int retval;

        /* Initialize the rest of the device structure. */

        lp = dev->priv;

        lp->hw.owner = THIS_MODULE;
        lp->hw.command = com20020_command;
        lp->hw.status = com20020_status;
        lp->hw.intmask = com20020_setmask;
        lp->hw.reset = com20020_reset;
        lp->hw.copy_to_card = com20020_copy_to_card;
        lp->hw.copy_from_card = com20020_copy_from_card;
        lp->hw.close = com20020_close;

        // dev->set_multicast_list = com20020_set_mc_list; /*** RTNET 
***/

        if (!dev->dev_addr[0])
                dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8);   /* FIXME: do 
this 
some other way! (not written by me - Chris) */

        SET_SUBADR(SUB_SETUP1);
        outb(lp->setup, _XREG);

        if (lp->card_flags & ARC_CAN_10MBIT)
        {
                SET_SUBADR(SUB_SETUP2);
                outb(lp->setup2, _XREG);
        
                /* must now write the magic "restart operation" command */
                mdelay(1);
                outb(0x18, _COMMAND);
        }

        lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 
1;
        /* Default 0x38 + register: Node ID */
        SETCONF;
        outb(dev->dev_addr[0], _XREG);

        /*** RTnet ***/

        /* reserve the irq */
        /*if (request_irq(dev->irq, &arcnet_interrupt, shared,
                        "arcnet (COM20020)", dev)) {
                BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
                return -ENODEV;
        }*/

        if (dev->irq == 0)
        return -EAGAIN;

        rt_stack_connect(dev, &STACK_manager);
        retval = rtdm_irq_request(&lp->irq_handle, dev->irq, 
arcnet_interrupt, 0,
                         "rt_arcnet", dev);
        if (retval)
        return retval;

        rtdm_irq_enable(&lp->irq_handle);
        
        /*** RTnet ***/

        dev->base_addr = ioaddr;

        BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
               lp->card_name, dev->dev_addr[0], dev->base_addr, 
dev->irq);

        if (lp->backplane)
                BUGMSG(D_NORMAL, "Using backplane mode.\n");

        if (lp->timeout != 3)
                BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", 
lp->timeout);

        BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
               lp->setup >> 1,
               clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 
0x0F) >> 1)]);

        /*** RTnet ***/

        /*if (register_netdev(dev)) {
                free_irq(dev->irq, dev);
                return -EIO;
        }*/
        
        if (rt_register_rtnetdev(dev))
     {
        rtdm_irq_free(&lp->irq_handle);
        return -EIO;
        }
                
        /*** RTnet ***/

        return 0;
}

3.) Ok. last question. It seems like I have a problem with module 
dependencies. The arcnet driver is set up to be loaded as four 
separate modules: arcnet.ko (the foundation), arc-rawmode.ko 
(provides rawmode encapsulation), com20020.ko (support for 
chipset), and com20020-pci.ko (support for pci-board).

I've done my homework and created four rt modules that compile and 
load into the kernel.. but the problem is that I cannot get them 
to load with 'rtnet start'. How do I specify dependencies in the 
'rtnet.conf' file? My dilemna is that if I specify com20020-pci 
without any extra work.. the program will not run because it 
cannot load the module without its dependencies.. BUT I cannot 
load rt_arcnet.ko and rt_com20020.ko before running 'rtnet start' 
because they both depend on the module rtnet!!

So I feel like I'm in a bit of a catch-22. Please tell me how to 
get around this problem.

Thank you so much for your help.

Chris Lightcap
University of Florida




On Tue Jul 11 04:03:33 EDT 2006, Jan Kiszka <[EMAIL PROTECTED]> 
wrote:

> Chris Lightcap wrote:
>> Hello all,
>> 
>> I'd like to implement a real-time arcnet driver to communicate 
>> with
>> our mitsubishi PA-10 robot using RTAI and RTnet. I found in the
> 
> You are welcome!
> 
>> mailing list archive that there was some interest in this topic 
>> about
>> a year ago.
>> 
>> .. Has anyone made progress with a real-time arcnet driver? is it
> 
> I'm personally not aware of any effort.
> 
>> possible to simply modify the existing driver as explained in the
>> porting documentation? are there any additional problems I should
>> know of beforehand?
> 
> I think to remember once browsing through the Linux arcnet stack 
> without
> finding anything that's fundamentally different from the "normal"
> networking stack. So all the pattern of RTnet /should/ apply to 
> arcnet
> as well. If you encounter something that doesn't fit on first 
> sight,
> feel free to discuss it here.
> 
> Please build your port on top of latest RTnet and only use RTDM 
> for
> interfacing the real-time Linux services - this will help to 
> integrate
> your work into the official version later.
> 
> Jan
> 
> 



--
LIGHTCAP,CHRISTOPHER A



-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
RTnet-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rtnet-developers

Reply via email to