LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices

Reply
 
Search this Thread
Old 05-06-2008, 07:30 AM   #1
gambuzo
LQ Newbie
 
Registered: May 2008
Posts: 3

Rep: Reputation: 0
3Com 3c905 - Problems trying to send a frame in my own kernel module


Hi all,

I've been trying to write a simple network driver for the 3Com 3c509B device in Linux, just for fun. Unfortunately, with no success. In my "module" I try to only send one frame, but it never gets downloaded by the NIC.

My kernel is 2.6.18, the bus is PCI.
I get all registers set as expected. I suppose something is wrong with DMA bus mastering. It seems as if the NIC doesn't download the data from the addresses I provide.
I get the dnInProg bit set in the DmaCtrl register (one of the NIC registers), so "Download is in progress", but in fact it doesn't work.

Below I put my code (somewhat modified to be short) in two versions, one with dma_pool_create/alloc() calls, and the other with dma_map_single(). Both produce the same results, but with no success (sending one frame). All of this runs after a successful request_irq().

I based the code on the "3C90x and 3C90xB NICs Technical Reference" from 3Com, published August 1998.

Could anybody help me ? I'm quite discouraged and frustrated. What is wrong with the code? Did I miss something to get DMA working? The NIC register details are not important here, I'm asking mainly about DMA.

###########################################################
// dma_map_single() version

#define FRAME_SIZE 60

// Example ARP Request with random padding
u8 string[FRAME_SIZE] =
{0xff,0xff,0xff,0xff,0xff,0xff,...};

unsigned long HostRegBaseAddr; // NIC registers
u32 *DPD_mem=NULL;
u8 *frame_mem=NULL;
dma_addr_t DPD = 0, frame = 0;

struct pci_dev *pdev = NULL;

// Reset the device
iowrite16(GlobalReset,HostRegBaseAddr+14);
while (ioread16(HostRegBaseAddr+14)& cmdInProgress)
printk("Waiting...\n");

// Enable indications and interrupts
iowrite16(SetIndicationEnable | txComplete|dnComplete,HostRegBaseAddr+14);
iowrite16(SetInterruptEnable | txComplete|dnComplete,HostRegBaseAddr+14);

if ((frame_mem=kmalloc(FRAME_SIZE, GFP_DMA)) != NULL)
{
for (i=0; i<FRAME_SIZE; i++)
frame_mem[i] = string[i];
}
else
{error...}

if ((DPD_mem = kmalloc(16, GFP_DMA)) != NULL)
{
// Construct the DPD
DPD_mem[0] = 0; // DnNextPtr
DPD_mem[1] = 0x80008000; // FSH
DPD_mem[2] = frame; // FirstDnFragAddr
DPD_mem[3] = 0x800000003c; // FirstDnFragLen
}
else {error...}

DPD = dma_map_single(&pdev->dev, DPD_mem, 16, DMA_TO_DEVICE);
if (!DPD) {error...}

frame = dma_map_single(&pdev->dev, frame_mem, FRAME_SIZE, DMA_TO_DEVICE);
if (!frame) {error...}

// Send the frame
iowrite16(TxEnable, HostRegBaseAddr+14);
iowrite32(DPD, HostRegBaseAddr+0x24);
...
#############################################################



###########################################################
// dma_pool_create/alloc() version

#define FRAME_SIZE 60

// Example ARP Request with random padding
u8 string[FRAME_SIZE] =
{0xff,0xff,0xff,0xff,0xff,0xff,...};

unsigned long HostRegBaseAddr; // NIC registers
struct dma_pool *DPD_pool=NULL, *frame_pool=NULL;
unsigned long DPD_handle=0, frame_handle=0;
dma_addr_t DPD = 0, frame = 0;

struct pci_dev *pdev = NULL;

// Reset the device
iowrite16(GlobalReset,HostRegBaseAddr+14);
while (ioread16(HostRegBaseAddr+14)& cmdInProgress)
printk("Waiting...\n");

// Enable indications and interrupts
iowrite16(SetIndicationEnable | txComplete|dnComplete,HostRegBaseAddr+14);
iowrite16(SetInterruptEnable | txComplete|dnComplete,HostRegBaseAddr+14);

// Allocate DMA-memory for storing the DPD
if ((DPD_pool = dma_pool_create("DPD_pool", &(pdev->dev), 16, 16, 4096)) == NULL)
{
printk(KERN_ALERT "DPD_pool error");
return -1;
}

if ((frame_pool = dma_pool_create("frame_pool", &(pdev->dev), FRAME_SIZE, 16, 4096)) == NULL)
{
printk(KERN_ALERT "frame_pool error");
return -1;
}

printk("Pools OK\n");

if ((DPD = dma_pool_alloc(DPD_pool, GFP_DMA, &DPD_handle)) == NULL)
{
printk(KERN_ALERT "DPD alloc error\n");
return -1;
}

if ((frame = dma_pool_alloc(frame_pool, GFP_DMA,
&frame_handle))==NULL)
{
printk(KERN_ALERT "frame alloc error\n");
return -1;
}

for (i=0; i<FRAME_SIZE; i++)
frame[i] = string[i];

// Construct the DPD
DPD[0] = 0; // DnNextPtr
DPD[1] = 0x80008000; // FSH
DPD[2] = frame_handle; // FirstDnFragAddr
DPD[3] = 0x8000003c; // FirstDnFragLen

// Send the frame
iowrite16(TxEnable, HostRegBaseAddr+14);
iowrite32(DPD_handle, HostRegBaseAddr+0x24);
...
#############################################################

Thank you,
gambuzo.

Last edited by gambuzo; 05-06-2008 at 07:33 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Send but not receive using Thinkpad with 3Com PC Card scottb Linux - Networking 1 07-15-2007 01:55 PM
3Com PC card can send but not receive slylock Linux - Networking 3 07-27-2005 08:52 PM
3Com PCI 3c905B Cyclone & 3c905 Boomerang on 2.6 kernel = not working! snakey66 Linux - Networking 2 07-24-2004 04:39 AM
3c59x.o module for 3c905 3com ethernet 100BaseTx(cyclone) farhan Linux - Networking 1 10-08-2003 03:41 PM
3c59x.o module for 3c905 3com ethernet 100BaseTx(cyclone) farhan Linux - Networking 0 10-08-2003 03:27 PM


All times are GMT -5. The time now is 09:35 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration