RTXI 1.3
plugins/ni_device/osiUserCode.cpp
Go to the documentation of this file.
00001 /*
00002 *  osiUserCode.cpp
00003 *
00004 *   
00005 *  osiUserCode.cpp holds the two user defined functions
00006 *  needed to port iBus to a target platform.
00007 *
00008 *  acquireBoard( ) -- constructs and initializes the iBus
00009 *
00010 *  releaseBoard( ) -- deletes and cleans up the iBus
00011 *
00012 *  There are also assorted helper functions which are also 
00013 *  platform specific.
00014 *
00015 * 
00016 *  $DateTime: 2006/07/27 23:51:45 $
00017 *
00018 */
00019 
00020 //Platform independent headers
00021 #include "osiBus.h"
00022 
00023 
00024 //Linux specific headers
00025 #include <stdio.h>
00026 #include <unistd.h>
00027 #include <fcntl.h>
00028 #include <sys/mman.h>
00029 #include <stdlib.h>
00030 //#include <asm/page.h>
00031 #include <sys/user.h>
00032 
00033 #ifndef MAP_32BIT
00034 #define MAP_32BIT 0
00035 #endif
00036 
00037 struct LinuxSpecific{
00038         u32 _fileDescriptor;
00039 };
00040 
00041 i32 FindPCICard(u32,u32*,u32*,u32*,u32*);
00042 i32 MapPCIMemory(u32,u32,u32,u32,void**,void**,i32*);
00043 
00044 
00045 /* Return iBus of first matching PCI/PXI card.
00046 */
00047 iBus* acquireBoard(u32 devBAR0,u32 devBAR1)
00048 {
00049         u32 temp_PCIID,devBAR0Len,devBAR1Len;
00050     //u32 devBAR0,devBAR1;
00051         i32 retval,fd;
00052         void *mem0,*mem1;
00053         iBus *bus;
00054         LinuxSpecific *privateIBus;
00055 
00056         u32 busNumber = 0; 
00057         u32 devNumber = 0; 
00058         u32 devLocation = 0;
00059         //sscanf (brdLocation,"PXI%d::%d::INSTR", &busNumber, &devNumber);
00060 
00061         //devLocation = (busNumber<<8) | ((devNumber&0x1f)<<3);
00062         //Find the PCI memory ranges from /proc/bus/pci/devices
00063         //retval=FindPCICard(devLocation,&devBAR0,&devBAR1,&devBAR0Len,&devBAR1Len);
00064         //if(retval<0) return NULL;
00065         //printf("PCI Device ID 0x%lx, BAR0 %lx-%lx, BAR1 %lx-%lx \n",devLocation,devBAR0,devBAR0Len,devBAR1,devBAR1Len);
00066 
00067     //devBAR0 = 0xfe7ff000;
00068     devBAR0Len = 4096;
00069 
00070     //devBAR1 = 0xfe7fe000;
00071     devBAR1Len = 4096;
00072 
00073         //Memory map /dev/mem to get access to the PCI Card's memory
00074         retval=MapPCIMemory(devBAR0,devBAR1,devBAR0Len,devBAR1Len,&mem0,&mem1, &fd);
00075         if(retval<0) return NULL;
00076         //printf("PCI Device ID 0x%lx, mem0 0x%lx, mem1 0x%lx\n",devLocation,mem0,mem1);
00077 
00078         //create a new iBus which uses the mmaped addresses of /dev/mem
00079         bus = new iBus(0, 0, mem0, mem1);
00080         bus->_physBar[0] = devBAR0;
00081         bus->_physBar[1] = devBAR1;
00082         bus->_physBar[2] = NULL;
00083         bus->_physBar[3] = NULL;
00084         bus->_physBar[4] = NULL;
00085         bus->_physBar[5] = NULL;
00086         
00087         privateIBus =  new LinuxSpecific;
00088         privateIBus->_fileDescriptor = fd;
00089         bus->_osSpecific = (void*)privateIBus;
00090 
00091         return bus;
00092 }
00093 
00094 void  releaseBoard(iBus *&bus)
00095 {
00096         LinuxSpecific *privateIBus;
00097         privateIBus = (LinuxSpecific*) bus->_osSpecific;
00098         
00099         //close /dev/mem
00100         close(privateIBus->_fileDescriptor);
00101 
00102         delete privateIBus;
00103         delete bus;
00104 }
00105 
00106 
00107 /*Find the system memory ranges for a given PCI card */
00108 i32 FindPCICard(u32 location,u32* BAR0,u32* BAR1,
00109                                                                                   u32* BAR0Len,u32* BAR1Len)
00110 {
00111         /*In Linux 2.4.4, the file /proc/bus/pci/devices tells us the memory
00112                 used for each PCI card.  It also tells us which interrupt
00113                 the PCI card is assigned.
00114                 */
00115                 
00116         int fd = open("/proc/bus/pci/devices", O_RDONLY);
00117         int i,retval;
00118         u32 currentLocation;
00119         char buffer[300];
00120         do{
00121                 i=0;
00122                 retval = read(fd,buffer,140);
00123                 i += 140;
00124                 while((buffer[i-1] != 0x0a)&&(retval>0)){
00125                         retval = read(fd,buffer+i,1);
00126                         i++;
00127                 }
00128                 buffer[i]=0;
00129                 sscanf(buffer,"%x %*x %*x %lx %lx %*x %*x %*x %*x %*x %lx %lx",
00130                                 &currentLocation,BAR0,BAR1,BAR0Len,BAR1Len);
00131         }while((currentLocation != location)&&(retval>0));
00132         close(fd);
00133         if(currentLocation == location) return 0;
00134                 else return -1;
00135 }
00136 
00137 
00138 /* Return pointers to the PCI card's registers.
00139 */
00140 i32 MapPCIMemory(u32 BAR0, u32 BAR1, u32 BAR0Len, u32 BAR1Len,
00141                                   void** BAR0Mem, void** BAR1Mem, i32 *mmfd)
00142 {
00143         
00144         /*In Linux 2.4.4, the file /dev/mem can be memory mapped
00145                 to access system memory.  Since the PCI cards show up in system
00146                 memory, we can access the PCI cards through /dev/mem.
00147                 */
00148 
00149         /*Open /dev/mem */
00150         if ((*mmfd = open("/dev/mem", O_RDWR) ) < 0) {
00151                 printf("iBus: can't open /dev/mem \n");
00152                 return -1;
00153         }
00154         
00155         
00156         /*Get BAR1 */
00157         /*Get a Page aligned buffer */
00158         if ((*BAR1Mem = malloc(BAR1Len + (PAGE_SIZE-1))) == NULL) {
00159                 printf("iBus: allocation error \n");
00160                 return -1;
00161         }
00162 
00163         if ((ptr_uint_t)*BAR1Mem % PAGE_SIZE)
00164                 *BAR1Mem = (void*)((ptr_uint_t)*BAR1Mem + PAGE_SIZE - ((ptr_uint_t)*BAR1Mem % PAGE_SIZE));
00165 
00166         /*attach the device to a user address space */
00167         *BAR1Mem = (unsigned char *)mmap(
00168                 (caddr_t)*BAR1Mem, 
00169                 BAR1Len,
00170                 PROT_READ|PROT_WRITE,
00171                 MAP_SHARED|MAP_FIXED|MAP_32BIT|MAP_LOCKED,
00172                 *mmfd, 
00173                 (ptr_uint_t)BAR1
00174         );
00175          
00176         if ((long)*BAR1Mem < 0) {
00177                 printf("iBus: mmap error \n");
00178                 return -1;
00179         }
00180 
00181         
00182         /*Get BAR0 */
00183         /*Get a Page aligned buffer */
00184         if ((*BAR0Mem = malloc(BAR0Len + (PAGE_SIZE-1))) == NULL) {
00185                 printf("iBus: allocation error \n");
00186                 return -1;
00187         }
00188 
00189         if ((ptr_uint_t)*BAR0Mem % PAGE_SIZE)
00190                 *BAR0Mem = (void*)((ptr_uint_t)*BAR0Mem + PAGE_SIZE - ((ptr_uint_t)*BAR0Mem % PAGE_SIZE));
00191 
00192         /*attach the device to a user address space */
00193         *BAR0Mem = (unsigned char *)mmap(
00194                 (caddr_t)*BAR0Mem, 
00195                 BAR0Len,
00196                 PROT_READ|PROT_WRITE,
00197                 MAP_SHARED|MAP_FIXED|MAP_32BIT|MAP_LOCKED,
00198                 *mmfd, 
00199                 (ptr_uint_t)BAR0
00200         );
00201          
00202         if ((long)*BAR0Mem < 0) {
00203                 printf("iBus: mmap error \n");
00204                 return -1;
00205         }
00206         return 0;
00207 }
00208 
00209 /*
00210 * DMA Memory support
00211 */
00212 tDMAMemory * iBus::allocDMA (u32 size)
00213 { 
00214         printf("dma alloc not supported\n"); 
00215         return NULL;
00216 }
00217 
00218 void iBus::freeDMA (tDMAMemory *mem)
00219 {}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines