![]() |
RTXI 1.3
|
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 ¤tLocation,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 {}