Hi RTer,

I have a problem regarding converting a drivers code from NonRT to RT
(RTL/RTAI). The application I have will not have any value if not
working in realtime so I have no choice ....

The driver is for a amcc PCI controller and maps one (or up to 4) pass
thru regions of the amcc provided memory on the pci addon board to the
user application following this scheme:

a) in the drivers code there will the processing of the mmap prepared as
follow:

static void
amcc_s5933_pt_setup (struct amcc_s5933 *dev, u32 badr, int number)
{
    u32         mask;

    /* we only support memory mapped PT regions */

    if (badr & PCI_BASE_ADDRESS_SPACE_IO)
        {
        pr_debug ("amcc: pt: PassThru region %d  IO-mapped", number);
        return;
        }
    else
        {
        pr_debug ("amcc: pt: PassThru region %d  mem-mapped", number);
        }
        
    /* get configuration */

    cli ();
    /*
    * writing all 1 to PCI_BASE_ADDR_x
    * reading the in this register set value (set by Controller)  
    * writing back the old value from init 
    */
    pcibios_write_config_dword (dev->bus, dev->function, badrs[number],
~0);
    pcibios_read_config_dword (dev->bus, dev->function, badrs[number],
&mask);
    pcibios_write_config_dword (dev->bus, dev->function, badrs[number],
badr);
    sti ();


    pr_debug ("amcc: pt: %d - mask %08lx, currValue %08lx\n", number,
              mask, badr);

   /* extract data      
    * in this way we get the size(-1) of the PCI region
    */

    mask &= PCI_BASE_ADDRESS_MEM_MASK;

    dev->ptnum++;

    (dev->pts[number - 1]).size = (~mask) + 1;
    (dev->pts[number - 1]).phys_addr = (badr &
PCI_BASE_ADDRESS_MEM_MASK);
    (dev->pts[number - 1]).virt_addr = ioremap ((dev->pts[number -
1]).phys_addr,
                                            (dev->pts[number -
1]).size);

    pr_debug ("amcc: PassThru: PTNo[%d] - Size: %d, PhysAddr: %08lx,
VirtAddr: %08lx\n", (number - 1),
              (dev->pts[number - 1]).size,
              (dev->pts[number - 1]).phys_addr,
              (dev->pts[number - 1]).virt_addr);
}



b) then the mmap is part of struct file_ops
static int amcc_s5933_mmap ( struct file *file, struct vm_area_struct
*vma )
{

int AREA = 0;
    unsigned long offset = vma->vm_offset;

    /* very simple for the moment - only pts[AREA] */

    switch(MINOR(file->f_dentry->d_inode->i_rdev))
        {
        case
AMCC_PT1_MMAP_MINOR:
                {
                pr_debug("amcc: MINOR 1 -- first PT Area\n");
                AREA = 0;
                }
                break;
        case AMCC_PT2_MMAP_MINOR:
                {
                pr_debug("amcc: MINOR 2 -- second PT Area\n");
                AREA = 1;
                }
                break;
        case
AMCC_PT3_MMAP_MINOR:
                {
                pr_debug("amcc: MINOR 3 -- third PT Area\n");
                AREA = 3;
                }
                break;
        case AMCC_PT4_MMAP_MINOR:
                {
                pr_debug("amcc: MINOR 4 -- forth PT Area\n");
                AREA = 4;
                }
                break;
                
        } //switch


    pr_debug ("amcc: mmap: start: %08lx, end: %08lx, offset: %08lx,
flags: %08lx\n",
              vma->vm_start, vma->vm_end, vma->vm_offset,
vma->vm_flags);

    /* check dimensions */

    if ((vma->vm_end - vma->vm_start + vma->vm_offset) >
amcc_dev.pts[AREA].size)
        return -EINVAL;


    /* get real address */

    vma->vm_offset += amcc_dev.pts[AREA].phys_addr;
    if (vma->vm_offset & ~PAGE_MASK)
        return -ENXIO;

    /* map pages */



if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
        {
        pgprot_val(vma->vm_page_prot) =
pgprot_noncached(pgprot_val(vma->vm_page_prot));
        vma->vm_flags |= VM_IO;
        pr_debug("pgprot_noncached ...");
        }


if ((vma->vm_offset) & (PAGE_SIZE-1))
        {
        pr_debug("amcc: pages not aligned\n");
        return -ENXIO;
        }
        
if ((vma->vm_end - vma->vm_start) > (0x20000 - vma->vm_offset))
        {
        pr_debug("amcc: PT too big !!!\n");
        return -EINVAL;
        }       

          
// remapping    | virtuell address | physical address | size |
protection */
if (remap_page_range (vma->vm_start, vma->vm_offset,(vma->vm_end -
vma->vm_start), vma->vm_page_prot))
        {
        return -EAGAIN;
        }
else
        {
        pr_debug("vma->vm_start(virtaddr): %08lx
vma->vm_offset(physaddr):
%08lx\n(vma->vm_end - vma->vm_start)(size): %08lx 
vma->vm_page_prot(protection): %08lx\n)", 
        vma->vm_start, vma->vm_offset,(vma->vm_end - vma->vm_start),
vma->vm_page_prot);
        }

/*
    vma->vm_inode = inode;
    inode->i_count++;
*/

return 0;
}

c) the app uses the mmap in this manner:

 pt = (__u32 *) mmap (Start, 0x20000, (PROT_READ | PROT_WRITE),
MAP_SHARED,
    amcc_fd, (off_t) 0L); // 128KByte  mapped


Now the question: if I will have to do the handling of the memory 
formerly mapped in user spaced in my module now, what will I have to do?
I am not the original autor of the modules code and have only some
overview.




-- 
Jens Lauer
TU Chemnitz /Germany
09107 Chemnitz
Fakultaet fuer Elektrotechnik und Informationstechnik
Lehrstuhl Elektrische Maschinen und Antriebe (Prof. Hofmann)

Tel +49 (0)371 531 3379
Fax +49 (0)371 531 3324 
[EMAIL PROTECTED]
-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
---
For more information on Real-Time Linux see:
http://www.rtlinux.org/rtlinux/

Reply via email to