<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Hello,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I have the master up and running and can connect from a kernel module. I’m trying to mmap a customer struct in the kernel-space to the user-space to exchange process data. I’ve been trying for days, but can’t get it to work.
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Everything seems to go fine in kernel-space and the user-space program can open the mmap'd file, but the data is absolute garbage. I must not be allocating the memory properly or something else fundamentally wrong. I've spent days reading
 on the Internet, but I always get the same result. Can someone tell me what I'm doing wrong?<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks in advance,<o:p></o:p></p>
<p class="MsoNormal">Tom<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    ////////////////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal">    // Includes<o:p></o:p></p>
<p class="MsoNormal">    ////////////////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    #include <linux/module.h><o:p></o:p></p>
<p class="MsoNormal">    #include <linux/kernel.h><o:p></o:p></p>
<p class="MsoNormal">    #include <linux/init.h><o:p></o:p></p>
<p class="MsoNormal">    #include <linux/fs.h><o:p></o:p></p>
<p class="MsoNormal">    #include <linux/debugfs.h><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // for kfree, kmalloc<o:p></o:p></p>
<p class="MsoNormal">    #include <linux/slab.h><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // for mmap<o:p></o:p></p>
<p class="MsoNormal">    #include <linux/mm.h><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    #include "CtsSharedData.h"<o:p></o:p></p>
<p class="MsoNormal">    #include "ProcessData.h"<o:p></o:p></p>
<p class="MsoNormal">    #include "globals.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    /////////////////////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal">    // Private variables<o:p></o:p></p>
<p class="MsoNormal">    //////////////////////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Pointer to the file in debugfs RAM file system<o:p></o:p></p>
<p class="MsoNormal">   static struct dentry* _ocFile;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // keep track of how often the item is mapped<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    void<o:p></o:p></p>
<p class="MsoNormal">    mmap_open(struct vm_area_struct* vma)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        CtsProcessData* info = (CtsProcessData*)vma->vm_private_data;<o:p></o:p></p>
<p class="MsoNormal">        info->reference += 1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // keep track of how often the item is mapped<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    void<o:p></o:p></p>
<p class="MsoNormal">    mmap_close(struct vm_area_struct* vma)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        CtsProcessData* info = (CtsProcessData*)vma->vm_private_data;<o:p></o:p></p>
<p class="MsoNormal">                info->reference -= 1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p></o:p></p>
<p class="MsoNormal">    int <o:p></o:p></p>
<p class="MsoNormal">    mmap_fault(struct vm_area_struct* vma, struct vm_fault *vmf)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        unsigned long offset = vmf->pgoff << PAGE_SHIFT;<o:p></o:p></p>
<p class="MsoNormal">                CtsProcessData* priv = (CtsProcessData*) vma->vm_private_data;<o:p></o:p></p>
<p class="MsoNormal">        struct page *page;<o:p></o:p></p>
<p class="MsoNormal">                page = virt_to_page(priv + offset);<o:p></o:p></p>
<p class="MsoNormal">        if (!page)<o:p></o:p></p>
<p class="MsoNormal">                        return VM_FAULT_SIGBUS;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                get_page(page);<o:p></o:p></p>
<p class="MsoNormal">        vmf->page = page;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                priv->reference = 98765;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        PRINTF(CTSMSG_INFO "Vma fault, virtual_address = %p,"<o:p></o:p></p>
<p class="MsoNormal">                " offset = %lu, page = %p\n", vmf->virtual_address, offset, page);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                return 0;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    } <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    static struct vm_operations_struct mmap_vm_ops = <o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                .open = mmap_open,<o:p></o:p></p>
<p class="MsoNormal">        .close = mmap_close,<o:p></o:p></p>
<p class="MsoNormal">        .fault = mmap_fault,<o:p></o:p></p>
<p class="MsoNormal">    };<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Initilize the vm_area_struct to point to the mmap functions specific to<o:p></o:p></p>
<p class="MsoNormal">    // our implementation.<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    int<o:p></o:p></p>
<p class="MsoNormal">    ocMapPdTable(struct file* filp, struct vm_area_struct* vma)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        PRINTF(CTSMSG_INFO": BEGIN: ocMapPdTable \n");<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        //<o:p></o:p></p>
<p class="MsoNormal">                // The operations table describes the specific methods<o:p></o:p></p>
<p class="MsoNormal">        // that can operate on this particular instance of the object.<o:p></o:p></p>
<p class="MsoNormal">                //<o:p></o:p></p>
<p class="MsoNormal">        vma->vm_ops = &mmap_vm_ops;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                vma->vm_flags |= VM_RESERVED;<o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">        vma->vm_private_data = filp->private_data;<o:p></o:p></p>
<p class="MsoNormal">                mmap_open(vma);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        PRINTF(CTSMSG_INFO": END: ocMapPdTable \n");<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                return 0;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Frees the shared data table.<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    int<o:p></o:p></p>
<p class="MsoNormal">    ocClosePdTable(struct inode* inode, struct file* filp)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                CtsProcessData* info = filp->private_data;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                PRINTF(CTSMSG_INFO": BEGIN: ocClosePdTable \n");<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                kfree(info);<o:p></o:p></p>
<p class="MsoNormal">                filp->private_data = NULL;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                PRINTF(CTSMSG_INFO": END: ocClosePdTable \n");<o:p></o:p></p>
<p class="MsoNormal">                return 0;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Allocate the shared memory<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    int<o:p></o:p></p>
<p class="MsoNormal">    ocOpenPdTable(struct inode* inode, struct file* filp)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                CtsProcessData* info;    <o:p></o:p></p>
<p class="MsoNormal">                // unsigned long virt_addr;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                PRINTF(CTSMSG_INFO": BEGIN ocOpenPdTable\n");    
<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                //<o:p></o:p></p>
<p class="MsoNormal">                // Create the process data in the kernel's memory<o:p></o:p></p>
<p class="MsoNormal">                //<o:p></o:p></p>
<p class="MsoNormal">                info = kmalloc(sizeof(CtsProcessData), GFP_KERNEL);<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                /* round it up to the page bondary */  <o:p>
</o:p></p>
<p class="MsoNormal">                // kmalloc_area = (int *)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK); 
<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                //<o:p></o:p></p>
<p class="MsoNormal">                // initialize the process data instance<o:p></o:p></p>
<p class="MsoNormal">                //<o:p></o:p></p>
<p class="MsoNormal">                memset(info, 0, sizeof(CtsProcessData));<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                info->rawData = (CtsRawData*)kmalloc(sizeof(CtsRawData) * 1000, GFP_KERNEL);<o:p></o:p></p>
<p class="MsoNormal">                if (info->rawData == NULL)<o:p></o:p></p>
<p class="MsoNormal">                {<o:p></o:p></p>
<p class="MsoNormal">                                PRINTF("Failed to allocate memory for raw data!");<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">                else<o:p></o:p></p>
<p class="MsoNormal">                {<o:p></o:p></p>
<p class="MsoNormal">                                memset(info->rawData, 0, (sizeof(CtsRawData) * 1000));<o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">                                //<o:p></o:p></p>
<p class="MsoNormal">                                // FOR TESTING ONLY! Delete!<o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">                                FPSET_16_16(info->rawData[0].load, 12, 0);<o:p></o:p></p>
<p class="MsoNormal">                                FPSET_16_16(info->rawData[0].position, 99, 0);<o:p></o:p></p>
<p class="MsoNormal">                                info->rawData[0].ticks = 54321;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                filp->private_data = info;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                PRINTF(CTSMSG_INFO": END ocOpenPdTable\n");        
<o:p></o:p></p>
<p class="MsoNormal">                return 0;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    static const struct file_operations oc_fops = <o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                .open = ocOpenPdTable,<o:p></o:p></p>
<p class="MsoNormal">                .release = ocClosePdTable,<o:p></o:p></p>
<p class="MsoNormal">                .mmap = ocMapPdTable,<o:p></o:p></p>
<p class="MsoNormal">    };         <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    //////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal">    // PUBLIC INTERFACE FUNCTIONS<o:p></o:p></p>
<p class="MsoNormal">    //////////////////////////////////////////////////<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Create the file in the debugfs RAM file system, which will trigger<o:p></o:p></p>
<p class="MsoNormal">    // mapping the memory<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    int <o:p></o:p></p>
<p class="MsoNormal">    ctsSharedTableCreate(void)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                BOOL ret = FALSE;<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                PRINTF(CTSMSG_INFO": BEGIN ocSharedTableCreate\n");<o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">                _ocFile = debugfs_create_file(<o:p></o:p></p>
<p class="MsoNormal">                                CTSRT_DEBUGFS_SHAREDTABLE, // a pointer to a string containing the name of<o:p></o:p></p>
<p class="MsoNormal">                                                                                                                                                                                                                                               
 // the file to create.<o:p></o:p></p>
<p class="MsoNormal">                                0644, // the permission that the file should have<o:p></o:p></p>
<p class="MsoNormal">                                NULL, // a pointer to the parent entry for this file.
<o:p></o:p></p>
<p class="MsoNormal">                                                                                // This should be a directory dentry if set.
<o:p></o:p></p>
<p class="MsoNormal">                                                                                // If this paramater is NULL, then the file will be created in the
<o:p></o:p></p>
<p class="MsoNormal">                                                                                // root of the debugfs filesystem.<o:p></o:p></p>
<p class="MsoNormal">                                NULL, // a pointer to something that the caller will want to get to later
<o:p></o:p></p>
<p class="MsoNormal">                                                                                // on. The inode.i_private pointer will point to this
<o:p></o:p></p>
<p class="MsoNormal">                                                                                // value on the open call.<o:p></o:p></p>
<p class="MsoNormal">                                &oc_fops);  // a pointer to a struct file_operations that should be used
<o:p></o:p></p>
<p class="MsoNormal">                                                                                                                                // for this file.                   
<o:p></o:p></p>
<p class="MsoNormal">                                <o:p></o:p></p>
<p class="MsoNormal">                if (_ocFile == NULL)<o:p></o:p></p>
<p class="MsoNormal">                {<o:p></o:p></p>
<p class="MsoNormal">                                //<o:p></o:p></p>
<p class="MsoNormal">                                // Most likely, the kernel module crashed on exit and the file already<o:p></o:p></p>
<p class="MsoNormal">                                // exists. We don't have any way of deletlying it. The computer will<o:p></o:p></p>
<p class="MsoNormal">                                // need to be restarted.<o:p></o:p></p>
<p class="MsoNormal">                                //<o:p></o:p></p>
<p class="MsoNormal">                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate failed to create debugfs file!\n");           
<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">                else if ((int)_ocFile == -ENODEV)<o:p></o:p></p>
<p class="MsoNormal">                {<o:p></o:p></p>
<p class="MsoNormal">                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate failed because of ENODEV!\n");<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">                else<o:p></o:p></p>
<p class="MsoNormal">                {<o:p></o:p></p>
<p class="MsoNormal">                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate succeeded.\n");<o:p></o:p></p>
<p class="MsoNormal">                                ret = TRUE;<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">                <o:p></o:p></p>
<p class="MsoNormal">                return ret;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    <o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    // Close and delete the shared table and all associated memory.<o:p></o:p></p>
<p class="MsoNormal">    //<o:p></o:p></p>
<p class="MsoNormal">    void <o:p></o:p></p>
<p class="MsoNormal">    ctsSharedTableClose(void)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">                debugfs_remove(_ocFile);<o:p></o:p></p>
<p class="MsoNormal">    }          <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial","sans-serif";color:black">Thomas C. Bitsky Jr. | Lead Developer</span><span style="font-size:12.0pt;font-family:"Times New Roman","serif""><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial","sans-serif";color:#660000">ADC | <a href="http://automateddesign.com/" target="_blank"><span style="color:blue">automateddesign.com</span></a></span><span style="font-size:12.0pt;font-family:"Arial","sans-serif";color:black"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial","sans-serif";color:black">P: 630-783-1150 F: 630-783-1159 M: 630-632-6679<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>