Hi All,

 I am currently working on the realtek driver available in 
http://linuxgazette.net/156/jangir.html.

 When I run the driver, pci_request_regions is erring out as :
ifconfig rtl8139 up
SIOCSIFFLAGS: Device or resource busy
[root@asdlab realtek]# dmesg | tail -50
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
pci 0000:04:03.0: PCI INT A disabled
pci 0000:04:03.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
Device enabled
----------------------------------------------------------------
Base 0  Starting Address = 9c00 End Address = 9cff  Length = 256
This Port is I/O mapped. It is NON Prefetchable.This is readable and writable.
Base 1  Starting Address = fdaff000 End Address = fdaff0ff  Length = 256
This Port is Memory mapped. It is NON Prefetchable. This is readable and 
writable.
rtl8139_init is called
region is Memory mapped region
rtl8139_dev is not NULL
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_get_stats is called
rtl8139_open is called
IRQ handler type mismatch for IRQ 16
current handler: via@pci:0000:01:00.0
Pid: 8522, comm: ifconfig Tainted: P          2.6.27.5-117.fc10.i686 #1
 [<c04637e7>] setup_irq+0x213/0x22d
 [<f886d6c0>] ? rtl8139_interrupt+0x0/0x230 [real5]
 [<c04638ef>] request_irq+0xee/0x10c
 [<f886d4e6>] rtl8139_open+0x31/0x20b [real5]
 [<c0631062>] dev_open+0x76/0xb4
 [<c0630ae3>] dev_change_flags+0xa2/0x155
 [<c067143b>] devinet_ioctl+0x21a/0x49b
 [<c06721dc>] inet_ioctl+0x8e/0xa7
 [<c0625597>] sock_ioctl+0x1b4/0x1d8
 [<c06253e3>] ? sock_ioctl+0x0/0x1d8
 [<c049a0b6>] vfs_ioctl+0x22/0x69
 [<c049a347>] do_vfs_ioctl+0x24a/0x25d
 [<c04f7b0c>] ? selinux_file_ioctl+0x35/0x38
 [<c049a39a>] sys_ioctl+0x40/0x5a
 [<c0403c76>] syscall_call+0x7/0xb
 [<c06a007b>] ? init_intel_cacheinfo+0x0/0x421

I am attaching the code. Any clues as to why?

Thanks & Regards,
D.Giriprasad
#define REALTEK_VENDER_ID  0x10EC
#define REALTEK_DEVICE_ID   0x8139

//#define REALTEK_VENDER_ID 0x10b5 
//#define REALTEK_DEVICE_ID  0x9050 

//#define VENDOR_ID 0x10b5
//#define DEVICE_ID 0x9050

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>

int print_pci(struct pci_dev *pdev);

#define TX_BUF_SIZE  1536  /* should be at least MTU + 14 + 4 */
#define TOTAL_TX_BUF_SIZE  (TX_BUF_SIZE * NUM_TX_SIZE)

/* 8139 register offsets */
#define TSD0          0x10
#define TSAD0       0x20
#define RBSTART  0x30
#define CR               0x37
#define CAPR         0x38
#define IMR            0x3c
#define ISR             0x3e
#define TCR           0x40
#define RCR           0x44
#define MPC           0x4c
#define MULINT    0x5c

/* TSD register commands */
#define TxHostOwns    0x2000
#define TxUnderrun    0x4000
#define TxStatOK      0x8000
#define TxOutOfWindow 0x20000000
#define TxAborted     0x40000000
#define TxCarrierLost 0x80000000

/* CR register commands */
#define RxBufEmpty 0x01
#define CmdTxEnb   0x04
#define CmdRxEnb   0x08
#define CmdReset   0x10

/* ISR Bits */
#define RxOK       0x01
#define RxErr      0x02
#define TxOK       0x04
#define TxErr      0x08
#define RxOverFlow 0x10
#define RxUnderrun 0x20
#define RxFIFOOver 0x40
#define CableLen   0x2000
#define TimeOut    0x4000
#define SysErr     0x8000

#define INT_MASK (RxOK | RxErr | TxOK | TxErr | \
               RxOverFlow | RxUnderrun | RxFIFOOver | \
               CableLen | TimeOut | SysErr)
               
#define NUM_TX_SIZE 4

#define NUM_TX_DESC 4

/* Size of the in-memory receive ring. */
#define RX_BUF_LEN_IDX 2         /* 0==8K, 1==16K, 2==32K, 3==64K */
#define RX_BUF_LEN     (8192 << RX_BUF_LEN_IDX)
#define RX_BUF_PAD     16           /* see 11th and 12th bit of RCR: 0x44 */
#define RX_BUF_WRAP_PAD 2048   /* spare padding to handle pkt wrap */
#define RX_BUF_TOT_LEN  (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)

static void rtl8139_init_ring (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
static void rtl8139_chip_reset (void *ioaddr);

struct rtl8139_private 
{
        struct pci_dev *pci_dev;  /* PCI device */
        void *mmio_addr; /* memory mapped I/O addr */
        unsigned long regs_len; /* length of I/O or MMI/O region */
        unsigned int tx_flag;
        unsigned int cur_tx;
        unsigned int dirty_tx;
        unsigned char *tx_buf[NUM_TX_DESC];   /* Tx bounce buffers */
        unsigned char *tx_bufs;        /* Tx bounce buffer region. */
        dma_addr_t tx_bufs_dma;

        struct net_device_stats stats;
        unsigned char *rx_ring;
        dma_addr_t rx_ring_dma;
        unsigned int cur_rx;
};
     

static struct pci_dev* probe_for_realtek8139(void) 
{
        struct pci_dev *pdev = NULL;
        /* Ensure we are not working on a non-PCI system */
        //if(!pci_present( )) {
        //       printk("<1>pci not present\n");
        //       return pdev;
        //}
        //else
        //        printk("<1>pci device is present\n");

        /* Look for RealTek 8139 NIC */
        pdev = pci_find_device(REALTEK_VENDER_ID, REALTEK_DEVICE_ID, NULL);
        if(pdev) {
               //printk("Found PCI device with vendorid = %x deviceid = %x\n", 
REALTEK_VENDER_ID, REALTEK_DEVICE_ID);
               // device found, enable it 
               if(pci_enable_device(pdev)) {
                        //printk("Could not enable the device\n");
                       return NULL;
               }
               else
                        printk("Device enabled\n");
        }
        else {
                //printk("device not found\n");
               return pdev;
        }
        return pdev;
}


#define DRIVER "rtl8139"
static struct net_device *rtl8139_dev = NULL;

static int rtl8139_init(struct pci_dev *pdev, struct net_device **dev_out) 
{
        struct net_device *dev;
        struct rtl8139_private *tp;

        /* 
         * alloc_etherdev allocates memory for dev and dev->priv.
         * dev->priv shall have sizeof(struct rtl8139_private) memory
         * allocated.
         */
        printk("rtl8139_init is called\n");
        dev = alloc_etherdev(sizeof(struct rtl8139_private));
        if(!dev) {
                printk("Could not allocate etherdev\n");
               return -1;
        }
        //printk("rtl8139_init , initializing the structure struct net_device 
\n");

        tp = dev->priv;
        tp->pci_dev = pdev;
        *dev_out = dev;
        //printk("rtl8139_init exiting .........\n");

        return 0;
}


static void rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs 
*regs) 
{
        struct net_device *dev = (struct net_device*)dev_instance;
        struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        unsigned short isr = readw(ioaddr + ISR);
        
        /* clear all interrupt.
         * Specs says reading ISR clears all interrupts and writing
         * has no effect. But this does not seem to be case. I keep on
         * getting interrupt unless I forcibly clears all interrupt :-(
         */
        writew(0xffff, ioaddr + ISR);

        if((isr & TxOK) || (isr & TxErr)) 
        {
               while((tp->dirty_tx != tp->cur_tx) || netif_queue_stopped(dev))
               {
                       unsigned int txstatus = 
                               readl(ioaddr + TSD0 + tp->dirty_tx * 
sizeof(int));

                       if(!(txstatus & (TxStatOK | TxAborted | TxUnderrun)))
                               break; /* yet not transmitted */

                       if(txstatus & TxStatOK) {
                                printk("Transmit OK interrupt\n");
                               tp->stats.tx_bytes += (txstatus & 0x1fff);
                               tp->stats.tx_packets++;
                       }
                       else {
                                printk("Transmit Error interrupt\n");
                               tp->stats.tx_errors++;
                       }
                               
                       tp->dirty_tx++;
                       tp->dirty_tx = tp->dirty_tx % NUM_TX_DESC;

                       if((tp->dirty_tx == tp->cur_tx) & 
netif_queue_stopped(dev))
                       {
                                printk("waking up queue\n");
                               netif_wake_queue(dev);
                       }
               }
        }

        if(isr & RxErr) {
               /* TODO: Need detailed analysis of error status */
                printk("receive err interrupt\n");
               tp->stats.rx_errors++;
        }

        if(isr & RxOK) {
                printk("receive interrupt received\n");
               while((readb(ioaddr + CR) & RxBufEmpty) == 0)
               {
                       unsigned int rx_status;
                       unsigned short rx_size;
                       unsigned short pkt_size;
                       struct sk_buff *skb;

                       if(tp->cur_rx > RX_BUF_LEN)
                               tp->cur_rx = tp->cur_rx % RX_BUF_LEN;
        
                       /* TODO: need to convert rx_status from little to host 
endian
                        * XXX: My CPU is little endian only :-)
                        */
                       rx_status = *(unsigned int*)(tp->rx_ring + tp->cur_rx);
                       rx_size = rx_status >> 16;
                       
                       /* first two bytes are receive status register 
                        * and next two bytes are frame length
                        */
                       pkt_size = rx_size - 4;

                       /* hand over packet to system */
                       skb = dev_alloc_skb (pkt_size + 2);
                       if (skb) {
                               skb->dev = dev;
                               skb_reserve (skb, 2); /* 16 byte align the IP 
fields */

                               skb_copy_and_csum_dev(skb, tp->rx_ring + 
tp->cur_rx + 4); 
                               //eth_copy_and_sum( skb, tp->rx_ring + 
tp->cur_rx + 4, pkt_size, 0);

                               skb_put (skb, pkt_size);
                               skb->protocol = eth_type_trans (skb, dev);
                               netif_rx (skb);

                               dev->last_rx = jiffies;
                               tp->stats.rx_bytes += pkt_size;
                               tp->stats.rx_packets++;
                       } 
                       else {
                                printk("Memory squeeze, dropping packet.\n");
                               tp->stats.rx_dropped++;
                       }
               
                       /* update tp->cur_rx to next writing location  * /
                       tp->cur_rx = (tp->cur_rx + rx_size + 4 + 3) & ~3;

                       /* update CAPR */
                       writew(tp->cur_rx, ioaddr + CAPR);
               }
        }
        
        if(isr & CableLen)
                printk("cable length change interrupt\n");
        if(isr & TimeOut)
                printk("time interrupt\n");
        if(isr & SysErr)
                printk("system err interrupt\n");
        return;
}

static int rtl8139_open(struct net_device *dev) 
{
        int retval;
        struct rtl8139_private *tp = dev->priv;

        printk("rtl8139_open is called\n"); 
        /* get the IRQ
         * second arg is interrupt handler
         * third is flags, 0 means no IRQ sharing
         */
        retval = request_irq(dev->irq, rtl8139_interrupt, 0 , dev->name, NULL);
        //retval = request_irq(dev->irq, rtl8139_interrupt, SA_INTERRUPT, 
dev->name, dev);
        if(retval)
               return retval;

        /* get memory for Tx buffers
         * memory must be DMAable
         */
        tp->tx_bufs = pci_alloc_consistent(
                       tp->pci_dev, TOTAL_TX_BUF_SIZE, &tp->tx_bufs_dma);
        
        if(!tp->tx_bufs) {
               free_irq(dev->irq, dev);
               return -ENOMEM;
        }
        tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, 
&tp->rx_ring_dma);

        if((!tp->tx_bufs)  || (!tp->rx_ring)) {
                free_irq(dev->irq, dev);

                if(tp->tx_bufs) {
                               pci_free_consistent(tp->pci_dev, 
TOTAL_TX_BUF_SIZE, tp->tx_bufs, tp->tx_bufs_dma);
                               tp->tx_bufs = NULL;
                       }
                if(tp->rx_ring) {
                               pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, 
tp->rx_ring, tp->rx_ring_dma);
                               tp->rx_ring = NULL;
                       }
                return -ENOMEM;
        }
         

        tp->tx_flag = 0;
        rtl8139_init_ring(dev);
        rtl8139_hw_start(dev);
        
        return 0;
}

static void rtl8139_init_ring (struct net_device *dev)
{
        struct rtl8139_private *tp = dev->priv;
        int i;

        tp->cur_tx = 0;
        tp->dirty_tx = 0;

        for (i = 0; i < NUM_TX_DESC; i++)
               tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
        
        return;
}

static void rtl8139_hw_start (struct net_device *dev)
{
        struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        u32 i;

        rtl8139_chip_reset(ioaddr);

        /* Must enable Tx/Rx before setting transfer thresholds! */
        writeb(CmdTxEnb | CmdRxEnb, ioaddr + CR);

        /* tx config */
        writel(0x00000600, ioaddr + TCR); /* DMA burst size 1024 */

        /* rx config */
        writel(((1 << 12) | (7 << 8) | (1 << 7) | 
                               (1 << 3) | (1 << 2) | (1 << 1)), ioaddr + RCR);

        /* init Tx buffer DMA addresses */
        for (i = 0; i < NUM_TX_DESC; i++) {
               writel(tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs),
                                      ioaddr + TSAD0 + (i * 4));
        }

        /* init RBSTART */
        writel(tp->rx_ring_dma, ioaddr + RBSTART);

        /* initialize missed packet counter */
        writel(0, ioaddr + MPC);

        /* no early-rx interrupts */
        writew((readw(ioaddr + MULINT) & 0xF000), ioaddr + MULINT);

        /* Enable all known interrupts by setting the interrupt mask. */
        writew(INT_MASK, ioaddr + IMR);

        netif_start_queue (dev);
        return;
}

static void rtl8139_chip_reset (void *ioaddr)
{
        int i;

        /* Soft reset the chip. */
        writeb(CmdReset, ioaddr + CR);

        /* Check that the chip has finished the reset. */
        for (i = 1000; i > 0; i--) {
               barrier();
               if ((readb(ioaddr + CR) & CmdReset) == 0)
                       break;
               udelay (10);
        }
        return;
}
               

static int rtl8139_stop(struct net_device *dev) 
{
        printk("rtl8139_open is called\n");
        free_irq(dev->irq, NULL);
        return 0;
}

static int rtl8139_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
        struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        unsigned int entry = tp->cur_tx;
        unsigned int len = skb->len;
#define ETH_MIN_LEN 60  /* minimum Ethernet frame size */
         printk("rtl8139_start_xmit is called\n");
        if (len < TX_BUF_SIZE) {
               if(len < ETH_MIN_LEN)
                       memset(tp->tx_buf[entry], 0, ETH_MIN_LEN);
               skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
               dev_kfree_skb(skb);
        } else {
               skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
               dev_kfree_skb(skb);
               return 0;
        }
        writel(tp->tx_flag | max(len, (unsigned int)ETH_MIN_LEN), 
                       ioaddr + TSD0 + (entry * sizeof (u32)));
        entry++;
        tp->cur_tx = entry % NUM_TX_DESC;

        if(tp->cur_tx == tp->dirty_tx) {
               netif_stop_queue(dev);
        }
        return 0;
}


static struct net_device_stats* rtl8139_get_stats(struct net_device *dev) 
{
         struct rtl8139_private *tp;
         printk("rtl8139_get_stats is called\n");
         tp = netdev_priv(dev);
         return &tp->stats;
        //return 0;
}

int init_module(void) 
{
        struct pci_dev *pdev;
        unsigned long mmio_start, mmio_end, mmio_len, mmio_flags;
        void *ioaddr;
        struct rtl8139_private *tp;
        int i, err = 0;

        pdev = probe_for_realtek8139( );
        if(!pdev)
               return 0;

        print_pci(pdev);
        if(rtl8139_init(pdev, &rtl8139_dev)) {
                printk("Could not initialize device\n");
               return 0;
        }

        tp = rtl8139_dev->priv; // rtl8139 private information 
        
        //printk("Reading the PCI BAR registers \n");
        // get PCI memory mapped I/O space base address from BAR1 
        mmio_start = pci_resource_start(pdev, 1);
        mmio_end = pci_resource_end(pdev, 1);
        mmio_len = pci_resource_len(pdev, 1);
        mmio_flags = pci_resource_flags(pdev, 1);

        //printk("Checking the PCI BAR registers for Memory mapped flag \n");
        // make sure above region is MMI/O 
        if(!(mmio_flags & IORESOURCE_MEM)) {
                printk("region not MMI/O region\n");
               goto cleanup1;
        }
        else
                printk("region is Memory mapped region\n");
        
        //printk("Calling pci_request_region \n");
        // get PCI memory space 
        if(pci_request_regions(pdev, DRIVER)) {
                printk("Could not get PCI region\n");
               goto cleanup1;
        }

        //printk("Calling pci_set_master\n");
        pci_set_master(pdev);

        //printk("Calling ioremap\n");
        // ioremap MMI/O region 
        ioaddr = ioremap(mmio_start, mmio_len);
        if(!ioaddr) {
                printk("Could not ioremap\n");
               goto cleanup2;
        }

        //printk("Assigning ioaddress and length \n");
        rtl8139_dev->base_addr = (long)ioaddr;
        tp->mmio_addr = ioaddr;
        tp->regs_len = mmio_len;

        // UPDATE NET_DEVICE 

        //printk("Assigning hardware address \n");
        for(i = 0; i < 6; i++) {  // Hardware Address 
               rtl8139_dev->dev_addr[i] = readb(rtl8139_dev->base_addr+i);
               rtl8139_dev->broadcast[i] = 0xff;
        }
        rtl8139_dev->hard_header_len = 14;

        //printk("Assigning function address \n");
        memcpy(rtl8139_dev->name, DRIVER, sizeof(DRIVER)); // Device Name 
        rtl8139_dev->irq = pdev->irq;  // Interrupt Number 
        rtl8139_dev->open = rtl8139_open;
        rtl8139_dev->stop = rtl8139_stop;
        rtl8139_dev->hard_start_xmit = rtl8139_start_xmit;
        rtl8139_dev->get_stats = rtl8139_get_stats;

        if(rtl8139_dev != NULL)
             printk("rtl8139_dev is not NULL\n");

        //printk("Calling register_netdev \n");
        // register the device 
        if(register_netdev(rtl8139_dev)) {
                printk("Could not register netdevice\n");
               goto cleanup0;
        } 
        //printk("AFTEr the call to register_netdev \n");
        goto noerror;

cleanup0:
        //printk("Error so, unregister_netdev \n");
        unregister_netdev(rtl8139_dev);
        err = 1;
cleanup2:
        //printk("Error so, unmap \n");
        iounmap(tp->mmio_addr);
        err = 1;
cleanup1:
        //printk("Error so, pci_release_regions \n");
        pci_release_regions(tp->pci_dev);
        err = 1;

noerror:
        //printk("Init function exiting fine ...............\n");
        return err;
}
               


void cleanup_module(void) 
{
        struct rtl8139_private *tp;
        tp = rtl8139_dev->priv;

        iounmap(tp->mmio_addr);
        pci_release_regions(tp->pci_dev);

        unregister_netdev(rtl8139_dev);
        pci_disable_device(tp->pci_dev);
        return;
}




// Should be called after pci_find_device and pci_enable_device have been called

int print_pci(struct pci_dev *dev)
{
        int i;
        int start, end, length, resflags;

        for (i = 0; i < 6; i++)
        {
                start = pci_resource_start (dev, i);
                if (!start)
                        continue;
                end = pci_resource_end (dev, i);
                length = pci_resource_len (dev, i);
                resflags = pci_resource_flags (dev, i);

                if (resflags & IORESOURCE_IO)
                {
                        
printk("----------------------------------------------------------------\n");
                        printk("Base %d  Starting Address = %x End Address = %x 
 Length = %d\n",i, start, end, length);
                        printk ("This Port is I/O mapped. ");
                        if (resflags & IORESOURCE_PREFETCH)
                                printk ("It is Prefetchable.");
                        else
                                printk ("It is NON Prefetchable.");

                        if (resflags & IORESOURCE_READONLY)
                                printk ("This is read only.\n");
                        else
                                printk ("This is readable and writable.\n");

                        if (check_region (start, length) < 0)
                                printk
                                ("Base %d starting Address = %x  End Address = 
%x Length = %d resource is not available \n",
                                        i, start, end, length);
                        //else if (request_region (start, length, DRIVER_NAME) 
< 0)
                //               printk ("The Resource is not allocated for BAR 
%d\n", i);
                //      else
                //              printk ("The Resource is allocated for BAR 
%d\n", i);
                }
                else
                {
                        if (resflags & IORESOURCE_MEM)
                        {
                                printk
                                ("Base %d  Starting Address = %x End Address = 
%x  Length = %d\n",i, start, end, length);
                                printk ("This Port is Memory mapped. ");
                                if (resflags & IORESOURCE_PREFETCH)
                                        printk ("It is Prefetchable. ");
                                else
                                        printk ("It is NON Prefetchable. ");

                                if (resflags & IORESOURCE_READONLY)
                                        printk ("It is read only.\n");
                                else
                                        printk ("This is readable and 
writable.\n");
                                if (check_mem_region (start, length) < 0)
                                 printk
                                 ("Base %d starting Address = %x  End Address = 
%x Length = %d resource is not available \n",
                                        i, start, end, length);
                                else
                                {
                                        //if (request_mem_region (start, 
length, DRIVER_NAME) < 0)
                                        //      printk("The Resource is not 
allocated for BAR %d\n", i);
                                        //else
                                        //      printk ("The Resource is 
allocated for BAR %d\n", i);
                                }
                        }
                }
        }
        

        return 0;
}


_______________________________________________
india mailing list
[email protected]
https://admin.fedoraproject.org/mailman/listinfo/india

Reply via email to