cli.c 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206
  1. #define _POSIX_C_SOURCE 200112L
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <strings.h>
  6. #include <stdint.h>
  7. #include <stdarg.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <sys/time.h>
  11. #include <sys/ioctl.h>
  12. #include <sys/mman.h>
  13. #include <errno.h>
  14. #include <alloca.h>
  15. #include <arpa/inet.h>
  16. #include <sys/types.h>
  17. #include <dirent.h>
  18. #include <pthread.h>
  19. #include <getopt.h>
  20. #include "pcitool/sysinfo.h"
  21. //#include "pci.h"
  22. #include "tools.h"
  23. #include "kernel.h"
  24. #include "error.h"
  25. /* defines */
  26. #define MAX_KBUF 14
  27. //#define BIGBUFSIZE (512*1024*1024)
  28. #define BIGBUFSIZE (1024*1024)
  29. #define DEFAULT_FPGA_DEVICE "/dev/fpga0"
  30. #define LINE_WIDTH 80
  31. #define SEPARATOR_WIDTH 2
  32. #define BLOCK_SEPARATOR_WIDTH 2
  33. #define BLOCK_SIZE 8
  34. #define BENCHMARK_ITERATIONS 128
  35. #define isnumber pcilib_isnumber
  36. #define isxnumber pcilib_isxnumber
  37. #define isnumber_n pcilib_isnumber_n
  38. #define isxnumber_n pcilib_isxnumber_n
  39. typedef uint8_t access_t;
  40. typedef enum {
  41. GRAB_MODE_GRAB = 1,
  42. GRAB_MODE_TRIGGER = 2
  43. } GRAB_MODE;
  44. typedef enum {
  45. MODE_INVALID,
  46. MODE_INFO,
  47. MODE_LIST,
  48. MODE_BENCHMARK,
  49. MODE_READ,
  50. MODE_READ_REGISTER,
  51. MODE_WRITE,
  52. MODE_WRITE_REGISTER,
  53. MODE_RESET,
  54. MODE_GRAB,
  55. MODE_START_DMA,
  56. MODE_STOP_DMA,
  57. MODE_LIST_DMA,
  58. MODE_LIST_DMA_BUFFERS,
  59. MODE_READ_DMA_BUFFER,
  60. MODE_WAIT_IRQ,
  61. MODE_LIST_KMEM,
  62. MODE_READ_KMEM,
  63. MODE_FREE_KMEM
  64. } MODE;
  65. typedef enum {
  66. ACCESS_BAR,
  67. ACCESS_DMA,
  68. ACCESS_FIFO
  69. } ACCESS_MODE;
  70. typedef enum {
  71. FLAG_MULTIPACKET = 1,
  72. FLAG_WAIT = 2
  73. } FLAGS;
  74. typedef enum {
  75. FORMAT_RAW,
  76. FORMAT_HEADER,
  77. FORMAT_RINGFS
  78. } FORMAT;
  79. typedef enum {
  80. PARTITION_UNKNOWN,
  81. PARTITION_RAW,
  82. PARTITION_EXT4
  83. } PARTITION;
  84. typedef enum {
  85. OPT_DEVICE = 'd',
  86. OPT_MODEL = 'm',
  87. OPT_BAR = 'b',
  88. OPT_ACCESS = 'a',
  89. OPT_ENDIANESS = 'e',
  90. OPT_SIZE = 's',
  91. OPT_OUTPUT = 'o',
  92. OPT_TIMEOUT = 't',
  93. OPT_INFO = 'i',
  94. OPT_LIST = 'l',
  95. OPT_READ = 'r',
  96. OPT_WRITE = 'w',
  97. OPT_GRAB = 'g',
  98. OPT_QUIETE = 'q',
  99. OPT_HELP = 'h',
  100. OPT_RESET = 128,
  101. OPT_BENCHMARK,
  102. OPT_TRIGGER,
  103. OPT_DATA_TYPE,
  104. OPT_EVENT,
  105. OPT_TRIGGER_RATE,
  106. OPT_TRIGGER_TIME,
  107. OPT_RUN_TIME,
  108. OPT_FORMAT,
  109. OPT_BUFFER,
  110. OPT_LIST_DMA,
  111. OPT_LIST_DMA_BUFFERS,
  112. OPT_READ_DMA_BUFFER,
  113. OPT_START_DMA,
  114. OPT_STOP_DMA,
  115. OPT_WAIT_IRQ,
  116. OPT_ITERATIONS,
  117. OPT_LIST_KMEM,
  118. OPT_FREE_KMEM,
  119. OPT_READ_KMEM,
  120. OPT_FORCE,
  121. OPT_WAIT,
  122. OPT_MULTIPACKET
  123. } OPTIONS;
  124. static struct option long_options[] = {
  125. {"device", required_argument, 0, OPT_DEVICE },
  126. {"model", required_argument, 0, OPT_MODEL },
  127. {"bar", required_argument, 0, OPT_BAR },
  128. {"access", required_argument, 0, OPT_ACCESS },
  129. {"endianess", required_argument, 0, OPT_ENDIANESS },
  130. {"size", required_argument, 0, OPT_SIZE },
  131. {"output", required_argument, 0, OPT_OUTPUT },
  132. {"timeout", required_argument, 0, OPT_TIMEOUT },
  133. {"iterations", required_argument, 0, OPT_ITERATIONS },
  134. {"info", no_argument, 0, OPT_INFO },
  135. {"list", no_argument, 0, OPT_LIST },
  136. {"reset", no_argument, 0, OPT_RESET },
  137. {"benchmark", optional_argument, 0, OPT_BENCHMARK },
  138. {"read", optional_argument, 0, OPT_READ },
  139. {"write", optional_argument, 0, OPT_WRITE },
  140. {"grab", optional_argument, 0, OPT_GRAB },
  141. {"trigger", optional_argument, 0, OPT_TRIGGER },
  142. {"data", required_argument, 0, OPT_DATA_TYPE },
  143. {"event", required_argument, 0, OPT_EVENT },
  144. {"run-time", required_argument, 0, OPT_RUN_TIME },
  145. {"trigger-rate", required_argument, 0, OPT_TRIGGER_RATE },
  146. {"trigger-time", required_argument, 0, OPT_TRIGGER_TIME },
  147. {"format", required_argument, 0, OPT_FORMAT },
  148. {"buffer", optional_argument, 0, OPT_BUFFER },
  149. {"start-dma", required_argument, 0, OPT_START_DMA },
  150. {"stop-dma", optional_argument, 0, OPT_STOP_DMA },
  151. {"list-dma-engines", no_argument, 0, OPT_LIST_DMA },
  152. {"list-dma-buffers", required_argument, 0, OPT_LIST_DMA_BUFFERS },
  153. {"read-dma-buffer", required_argument, 0, OPT_READ_DMA_BUFFER },
  154. {"wait-irq", optional_argument, 0, OPT_WAIT_IRQ },
  155. {"list-kernel-memory", no_argument, 0, OPT_LIST_KMEM },
  156. {"read-kernel-memory", required_argument, 0, OPT_READ_KMEM },
  157. {"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM },
  158. {"quiete", no_argument, 0, OPT_QUIETE },
  159. {"force", no_argument, 0, OPT_FORCE },
  160. {"multipacket", no_argument, 0, OPT_MULTIPACKET },
  161. {"wait", no_argument, 0, OPT_WAIT },
  162. {"help", no_argument, 0, OPT_HELP },
  163. { 0, 0, 0, 0 }
  164. };
  165. void Usage(int argc, char *argv[], const char *format, ...) {
  166. if (format) {
  167. va_list ap;
  168. va_start(ap, format);
  169. printf("Error %i: ", errno);
  170. vprintf(format, ap);
  171. printf("\n");
  172. va_end(ap);
  173. printf("\n");
  174. }
  175. printf(
  176. "Usage:\n"
  177. " %s <mode> [options] [hex data]\n"
  178. " Modes:\n"
  179. " -i - Device Info\n"
  180. " -l[l] - List (detailed) Data Banks & Registers\n"
  181. " -r <addr|reg|dmaX> - Read Data/Register\n"
  182. " -w <addr|reg|dmaX> - Write Data/Register\n"
  183. " --benchmark <barX|dmaX> - Performance Evaluation\n"
  184. " --reset - Reset board\n"
  185. " --help - Help message\n"
  186. "\n"
  187. " Event Modes:\n"
  188. " --trigger [event] - Trigger Events\n"
  189. " -g [event] - Grab Events\n"
  190. "\n"
  191. " DMA Modes:\n"
  192. " --start-dma <num>[r|w] - Start specified DMA engine\n"
  193. " --stop-dma [num[r|w]] - Stop specified engine or DMA subsystem\n"
  194. " --list-dma-engines - List active DMA engines\n"
  195. " --list-dma-buffers <dma> - List buffers for specified DMA engine\n"
  196. " --read-dma-buffer <dma:buf> - Read the specified buffer\n"
  197. " --wait-irq <source> - Wait for IRQ\n"
  198. "\n"
  199. " Kernel Modes:\n"
  200. " --list-kernel-memory - List kernel buffers\n"
  201. " --read-kernel-memory <blk> - Read the specified block of the kernel memory\n"
  202. " block is specified as: use:block_number\n"
  203. " --free-kernel-memory <use> - Cleans lost kernel space buffers (DANGEROUS)\n"
  204. " dma - Remove all buffers allocated by DMA subsystem\n"
  205. " #number - Remove all buffers with the specified use id\n"
  206. "\n"
  207. " Addressing:\n"
  208. " -d <device> - FPGA device (/dev/fpga0)\n"
  209. " -m <model> - Memory model (autodetected)\n"
  210. " pci - Plain\n"
  211. " ipecamera - IPE Camera\n"
  212. " -b <bank> - PCI bar, Register bank, or DMA channel\n"
  213. "\n"
  214. " Options:\n"
  215. " -s <size> - Number of words (default: 1)\n"
  216. " -a [fifo|dma]<bits> - Access type and bits per word (default: 32)\n"
  217. " -e <l|b> - Endianess Little/Big (default: host)\n"
  218. " -o <file> - Append output to file (default: stdout)\n"
  219. " -t <timeout> - Timeout in microseconds\n"
  220. "\n"
  221. " Event Options:\n"
  222. " --event <evt> - Specifies event for trigger and grab modes\n"
  223. " --data <type> - Data type to request for the events\n"
  224. " --run-time <us> - Grab/trigger events during the specified time\n"
  225. " --trigger-rate <tps> - Generate tps triggers per second\n"
  226. " --trigger-time <us> - Specifies delay between triggers in microseconds\n"
  227. " -s <num|unlimited> - Number of events to grab and trigger\n"
  228. " --format [type] - Specifies how event data should be stored\n"
  229. " raw - Just write all events sequentially\n"
  230. " add_header - Prefix events with 256 bit header\n"
  231. " ringfs - Write to RingFS\n"
  232. " --buffer [size] - Request data buffering, size in MB\n"
  233. "\n"
  234. " DMA Options:\n"
  235. " --multipacket - Read multiple packets\n"
  236. " --wait - Wait until data arrives\n"
  237. "\n"
  238. " Information:\n"
  239. " -q - Quiete mode (suppress warnings)\n"
  240. "\n"
  241. " Data:\n"
  242. " Data can be specified as sequence of hexdecimal number or\n"
  243. " a single value prefixed with '*'. In this case it will be\n"
  244. " replicated the specified amount of times\n"
  245. "\n\n",
  246. argv[0]);
  247. exit(0);
  248. }
  249. void Error(const char *format, ...) {
  250. va_list ap;
  251. va_start(ap, format);
  252. printf("Error %i: ", errno);
  253. vprintf(format, ap);
  254. if (errno) printf("\n errno: %s", strerror(errno));
  255. printf("\n\n");
  256. va_end(ap);
  257. exit(-1);
  258. }
  259. void Silence(const char *format, ...) {
  260. }
  261. void List(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, int details) {
  262. int i,j;
  263. pcilib_register_bank_description_t *banks;
  264. pcilib_register_description_t *registers;
  265. pcilib_event_description_t *events;
  266. pcilib_event_data_type_description_t *types;
  267. const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
  268. const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle);
  269. for (i = 0; i < PCILIB_MAX_BANKS; i++) {
  270. if (board_info->bar_length[i] > 0) {
  271. printf(" BAR %d - ", i);
  272. switch ( board_info->bar_flags[i]&IORESOURCE_TYPE_BITS) {
  273. case IORESOURCE_IO: printf(" IO"); break;
  274. case IORESOURCE_MEM: printf("MEM"); break;
  275. case IORESOURCE_IRQ: printf("IRQ"); break;
  276. case IORESOURCE_DMA: printf("DMA"); break;
  277. }
  278. if (board_info->bar_flags[i]&IORESOURCE_MEM_64) printf("64");
  279. else printf("32");
  280. printf(", Start: 0x%08lx, Length: 0x%8lx, Flags: 0x%08lx\n", board_info->bar_start[i], board_info->bar_length[i], board_info->bar_flags[i] );
  281. }
  282. }
  283. printf("\n");
  284. if ((dma_info)&&(dma_info->engines)) {
  285. printf("DMA Engines: \n");
  286. for (i = 0; dma_info->engines[i]; i++) {
  287. pcilib_dma_engine_description_t *engine = dma_info->engines[i];
  288. printf(" DMA %2d ", engine->addr);
  289. switch (engine->direction) {
  290. case PCILIB_DMA_FROM_DEVICE:
  291. printf("C2S");
  292. break;
  293. case PCILIB_DMA_TO_DEVICE:
  294. printf("S2C");
  295. break;
  296. case PCILIB_DMA_BIDIRECTIONAL:
  297. printf("BI ");
  298. break;
  299. }
  300. printf(" - Type: ");
  301. switch (engine->type) {
  302. case PCILIB_DMA_TYPE_BLOCK:
  303. printf("Block");
  304. break;
  305. case PCILIB_DMA_TYPE_PACKET:
  306. printf("Packet");
  307. break;
  308. }
  309. printf(", Address Width: %02lu bits\n", engine->addr_bits);
  310. }
  311. printf("\n");
  312. }
  313. if ((bank)&&(bank != (char*)-1)) banks = NULL;
  314. else banks = model_info->banks;
  315. if (banks) {
  316. printf("Banks: \n");
  317. for (i = 0; banks[i].access; i++) {
  318. printf(" 0x%02x %s", banks[i].addr, banks[i].name);
  319. if ((banks[i].description)&&(banks[i].description[0])) {
  320. printf(": %s", banks[i].description);
  321. }
  322. printf("\n");
  323. }
  324. printf("\n");
  325. }
  326. if (bank == (char*)-1) registers = NULL;
  327. else registers = model_info->registers;
  328. if (registers) {
  329. pcilib_register_bank_addr_t bank_addr;
  330. if (bank) {
  331. pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank);
  332. pcilib_register_bank_description_t *b = model_info->banks + bank_id;
  333. bank_addr = b->addr;
  334. if (b->description) printf("%s:\n", b->description);
  335. else if (b->name) printf("Registers of bank %s:\n", b->name);
  336. else printf("Registers of bank 0x%x:\n", b->addr);
  337. } else {
  338. printf("Registers: \n");
  339. }
  340. for (i = 0; registers[i].bits; i++) {
  341. const char *mode;
  342. if ((bank)&&(registers[i].bank != bank_addr)) continue;
  343. if (registers[i].type == PCILIB_REGISTER_BITS) {
  344. if (!details) continue;
  345. if (registers[i].bits > 1) {
  346. printf(" [%2u:%2u] - %s\n", registers[i].offset, registers[i].offset + registers[i].bits, registers[i].name);
  347. } else {
  348. printf(" [ %2u] - %s\n", registers[i].offset, registers[i].name);
  349. }
  350. continue;
  351. }
  352. if (registers[i].mode == PCILIB_REGISTER_RW) mode = "RW";
  353. else if (registers[i].mode == PCILIB_REGISTER_R) mode = "R ";
  354. else if (registers[i].mode == PCILIB_REGISTER_W) mode = " W";
  355. else mode = " ";
  356. printf(" 0x%02x (%2i %s) %s", registers[i].addr, registers[i].bits, mode, registers[i].name);
  357. if ((details > 0)&&(registers[i].description)&&(registers[i].description[0])) {
  358. printf(": %s", registers[i].description);
  359. }
  360. printf("\n");
  361. }
  362. printf("\n");
  363. }
  364. if (bank == (char*)-1) events = NULL;
  365. else {
  366. events = model_info->events;
  367. types = model_info->data_types;
  368. }
  369. if (events) {
  370. printf("Events: \n");
  371. for (i = 0; events[i].name; i++) {
  372. printf(" %s", events[i].name);
  373. if ((events[i].description)&&(events[i].description[0])) {
  374. printf(": %s", events[i].description);
  375. }
  376. if (types) {
  377. for (j = 0; types[j].name; j++) {
  378. if (types[j].evid & events[i].evid) {
  379. printf("\n %s", types[j].name);
  380. if ((types[j].description)&&(types[j].description[0])) {
  381. printf(": %s", types[j].description);
  382. }
  383. }
  384. }
  385. }
  386. }
  387. printf("\n");
  388. }
  389. }
  390. void Info(pcilib_t *handle, pcilib_model_description_t *model_info) {
  391. const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
  392. printf("Vendor: %x, Device: %x, Interrupt Pin: %i, Interrupt Line: %i\n", board_info->vendor_id, board_info->device_id, board_info->interrupt_pin, board_info->interrupt_line);
  393. List(handle, model_info, (char*)-1, 0);
  394. }
  395. #define BENCH_MAX_DMA_SIZE 4 * 1024 * 1024
  396. #define BENCH_MAX_FIFO_SIZE 1024 * 1024
  397. int Benchmark(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, size_t iterations) {
  398. int err;
  399. int i, j, errors;
  400. void *data, *buf, *check;
  401. void *fifo;
  402. struct timeval start, end;
  403. unsigned long time;
  404. size_t size, min_size, max_size;
  405. double mbs_in, mbs_out, mbs;
  406. size_t irqs;
  407. const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
  408. if (mode == ACCESS_DMA) {
  409. if (n) {
  410. min_size = n * access;
  411. max_size = n * access;
  412. } else {
  413. min_size = 1024;
  414. max_size = BENCH_MAX_DMA_SIZE;
  415. }
  416. for (size = min_size; size <= max_size; size *= 4) {
  417. mbs_in = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_FROM_DEVICE);
  418. mbs_out = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_TO_DEVICE);
  419. mbs = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_BIDIRECTIONAL);
  420. err = pcilib_wait_irq(handle, 0, 0, &irqs);
  421. if (err) irqs = 0;
  422. printf("%8i KB - ", size / 1024);
  423. printf("RW: ");
  424. if (mbs < 0) printf("failed ... ");
  425. else printf("%8.2lf MB/s", mbs);
  426. printf(", R: ");
  427. if (mbs_in < 0) printf("failed ... ");
  428. else printf("%8.2lf MB/s", mbs_in);
  429. printf(", W: ");
  430. if (mbs_out < 0) printf("failed ... ");
  431. else printf("%8.2lf MB/s", mbs_out);
  432. if (irqs) {
  433. printf(", IRQs: %lu", irqs);
  434. }
  435. printf("\n");
  436. }
  437. return 0;
  438. }
  439. if (bar == PCILIB_BAR_INVALID) {
  440. unsigned long maxlength = 0;
  441. for (i = 0; i < PCILIB_MAX_BANKS; i++) {
  442. if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + access))) {
  443. bar = i;
  444. break;
  445. }
  446. if (board_info->bar_length[i] > maxlength) {
  447. maxlength = board_info->bar_length[i];
  448. bar = i;
  449. }
  450. }
  451. if (bar < 0) Error("Data banks are not available");
  452. }
  453. if (n) {
  454. if ((mode == ACCESS_BAR)&&(n * access > board_info->bar_length[bar])) Error("The specified size (%i) exceeds the size of bar (%i)", n * access, board_info->bar_length[bar]);
  455. min_size = n * access;
  456. max_size = n * access;
  457. } else {
  458. min_size = access;
  459. if (mode == ACCESS_BAR) max_size = board_info->bar_length[bar];
  460. else max_size = BENCH_MAX_FIFO_SIZE;
  461. }
  462. err = posix_memalign( (void**)&buf, 256, max_size );
  463. if (!err) err = posix_memalign( (void**)&check, 256, max_size );
  464. if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", max_size);
  465. data = pcilib_map_bar(handle, bar);
  466. if (!data) Error("Can't map bar %i", bar);
  467. if (mode == ACCESS_FIFO) {
  468. fifo = data + (addr - board_info->bar_start[bar]) + (board_info->bar_start[bar] & pcilib_get_page_mask());
  469. // pcilib_resolve_register_address(handle, bar, addr);
  470. if (!fifo) Error("Can't resolve address (%lx) in bar (%u)", addr, bar);
  471. }
  472. if (mode == ACCESS_FIFO)
  473. printf("Transfer time (Bank: %i, Fifo: %lx):\n", bar, addr);
  474. else
  475. printf("Transfer time (Bank: %i):\n", bar);
  476. for (size = min_size ; size < max_size; size *= 8) {
  477. gettimeofday(&start,NULL);
  478. if (mode == ACCESS_BAR) {
  479. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  480. pcilib_memcpy(buf, data, size);
  481. }
  482. } else {
  483. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  484. for (j = 0; j < (size/access); j++) {
  485. pcilib_memcpy(buf + j * access, fifo, access);
  486. }
  487. }
  488. }
  489. gettimeofday(&end,NULL);
  490. time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
  491. printf("%8i bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
  492. fflush(0);
  493. gettimeofday(&start,NULL);
  494. if (mode == ACCESS_BAR) {
  495. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  496. pcilib_memcpy(data, buf, size);
  497. }
  498. } else {
  499. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  500. for (j = 0; j < (size/access); j++) {
  501. pcilib_memcpy(fifo, buf + j * access, access);
  502. }
  503. }
  504. }
  505. gettimeofday(&end,NULL);
  506. time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
  507. printf(", write: %8.2lf MB/s\n", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
  508. }
  509. pcilib_unmap_bar(handle, bar, data);
  510. printf("\n\nOpen-Transfer-Close time: \n");
  511. for (size = 4 ; size < max_size; size *= 8) {
  512. gettimeofday(&start,NULL);
  513. if (mode == ACCESS_BAR) {
  514. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  515. pcilib_read(handle, bar, 0, size, buf);
  516. }
  517. } else {
  518. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  519. pcilib_read_fifo(handle, bar, addr, access, size / access, buf);
  520. }
  521. }
  522. gettimeofday(&end,NULL);
  523. time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
  524. printf("%8i bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
  525. fflush(0);
  526. gettimeofday(&start,NULL);
  527. if (mode == ACCESS_BAR) {
  528. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  529. pcilib_write(handle, bar, 0, size, buf);
  530. }
  531. } else {
  532. for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
  533. pcilib_write_fifo(handle, bar, addr, access, size / access, buf);
  534. }
  535. }
  536. gettimeofday(&end,NULL);
  537. time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
  538. printf(", write: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
  539. if (mode == ACCESS_BAR) {
  540. gettimeofday(&start,NULL);
  541. for (i = 0, errors = 0; i < BENCHMARK_ITERATIONS; i++) {
  542. pcilib_write(handle, bar, 0, size, buf);
  543. pcilib_read(handle, bar, 0, size, check);
  544. if (memcmp(buf, check, size)) ++errors;
  545. }
  546. gettimeofday(&end,NULL);
  547. time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
  548. printf(", write-verify: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
  549. if (errors) printf(", errors: %u of %u", errors, BENCHMARK_ITERATIONS);
  550. }
  551. printf("\n");
  552. }
  553. printf("\n\n");
  554. free(check);
  555. free(buf);
  556. }
  557. #define pci2host16(endianess, value) endianess?
  558. /*
  559. typedef struct {
  560. size_t size;
  561. void *data;
  562. size_t pos;
  563. int multi_mode;
  564. } DMACallbackContext;
  565. static int DMACallback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
  566. DMACallbackContext *ctx = (DMACallbackContext*)arg;
  567. if ((ctx->pos + bufsize > ctx->size)||(!ctx->data)) {
  568. ctx->size *= 2;
  569. ctx->data = realloc(ctx->data, ctx->size);
  570. if (!ctx->data) {
  571. Error("Allocation of %i bytes of memory have failed", ctx->size);
  572. return 0;
  573. }
  574. }
  575. memcpy(ctx->data + ctx->pos, buf, bufsize);
  576. ctx->pos += bufsize;
  577. if (flags & PCILIB_DMA_FLAG_EOP) return 0;
  578. return 1;
  579. }
  580. */
  581. int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, size_t timeout, FILE *o) {
  582. void *buf;
  583. int i, err;
  584. size_t ret, bytes;
  585. size_t size = n * abs(access);
  586. int block_width, blocks_per_line;
  587. int numbers_per_block, numbers_per_line;
  588. pcilib_dma_engine_t dmaid;
  589. pcilib_dma_flags_t dma_flags = 0;
  590. numbers_per_block = BLOCK_SIZE / access;
  591. block_width = numbers_per_block * ((access * 2) + SEPARATOR_WIDTH);
  592. blocks_per_line = (LINE_WIDTH - 10) / (block_width + BLOCK_SEPARATOR_WIDTH);
  593. if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
  594. numbers_per_line = blocks_per_line * numbers_per_block;
  595. if (size) {
  596. buf = malloc(size);
  597. if (!buf) Error("Allocation of %zu bytes of memory has failed", size);
  598. } else {
  599. buf = NULL;
  600. }
  601. switch (mode) {
  602. case ACCESS_DMA:
  603. if (timeout == (size_t)-1) timeout = PCILIB_DMA_TIMEOUT;
  604. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
  605. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
  606. if (flags&FLAG_MULTIPACKET) dma_flags |= PCILIB_DMA_FLAG_MULTIPACKET;
  607. if (flags&FLAG_WAIT) dma_flags |= PCILIB_DMA_FLAG_WAIT;
  608. if (size) {
  609. err = pcilib_read_dma_custom(handle, dmaid, addr, size, dma_flags, timeout, buf, &bytes);
  610. if (err) Error("Error (%i) is reported by DMA engine", err);
  611. } else {
  612. dma_flags |= PCILIB_DMA_FLAG_IGNORE_ERRORS;
  613. size = 2048; bytes = 0;
  614. do {
  615. size *= 2;
  616. buf = realloc(buf, size);
  617. if (!buf) Error("Allocation of %zu bytes of memory has failed", size);
  618. err = pcilib_read_dma_custom(handle, dmaid, addr, size - bytes, dma_flags, timeout, buf + bytes, &ret);
  619. bytes += ret;
  620. if ((!err)&&(flags&FLAG_MULTIPACKET)) {
  621. err = PCILIB_ERROR_TOOBIG;
  622. if ((flags&FLAG_WAIT)==0) timeout = 0;
  623. }
  624. } while (err == PCILIB_ERROR_TOOBIG);
  625. }
  626. if (bytes <= 0) Error("No data is returned by DMA engine");
  627. size = bytes;
  628. n = bytes / abs(access);
  629. addr = 0;
  630. break;
  631. case ACCESS_FIFO:
  632. pcilib_read_fifo(handle, bar, addr, access, n, buf);
  633. addr = 0;
  634. break;
  635. default:
  636. pcilib_read(handle, bar, addr, size, buf);
  637. }
  638. if (endianess) pcilib_swap(buf, buf, abs(access), n);
  639. if (o) {
  640. printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access));
  641. fwrite(buf, abs(access), n, o);
  642. } else {
  643. for (i = 0; i < n; i++) {
  644. if (i) {
  645. if (i%numbers_per_line == 0) printf("\n");
  646. else {
  647. printf("%*s", SEPARATOR_WIDTH, "");
  648. if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, "");
  649. }
  650. }
  651. if (i%numbers_per_line == 0) printf("%8lx: ", addr + i * abs(access));
  652. switch (access) {
  653. case 1: printf("%0*hhx", access * 2, ((uint8_t*)buf)[i]); break;
  654. case 2: printf("%0*hx", access * 2, ((uint16_t*)buf)[i]); break;
  655. case 4: printf("%0*x", access * 2, ((uint32_t*)buf)[i]); break;
  656. case 8: printf("%0*lx", access * 2, ((uint64_t*)buf)[i]); break;
  657. }
  658. }
  659. printf("\n\n");
  660. }
  661. free(buf);
  662. return 0;
  663. }
  664. int ReadRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg) {
  665. int i;
  666. int err;
  667. const char *format;
  668. pcilib_register_bank_t bank_id;
  669. pcilib_register_bank_addr_t bank_addr;
  670. pcilib_register_value_t value;
  671. if (reg) {
  672. pcilib_register_t regid = pcilib_find_register(handle, bank, reg);
  673. bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank);
  674. format = model_info->banks[bank_id].format;
  675. if (!format) format = "%lu";
  676. err = pcilib_read_register_by_id(handle, regid, &value);
  677. // err = pcilib_read_register(handle, bank, reg, &value);
  678. if (err) printf("Error reading register %s\n", reg);
  679. else {
  680. printf("%s = ", reg);
  681. printf(format, value);
  682. printf("\n");
  683. }
  684. } else {
  685. // Adding DMA registers
  686. pcilib_get_dma_info(handle);
  687. if (model_info->registers) {
  688. if (bank) {
  689. bank_id = pcilib_find_bank(handle, bank);
  690. bank_addr = model_info->banks[bank_id].addr;
  691. }
  692. printf("Registers:\n");
  693. for (i = 0; model_info->registers[i].bits; i++) {
  694. if ((model_info->registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(model_info->registers[i].bank == bank_addr))&&(model_info->registers[i].type != PCILIB_REGISTER_BITS)) {
  695. bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[i].bank);
  696. format = model_info->banks[bank_id].format;
  697. if (!format) format = "%lu";
  698. err = pcilib_read_register_by_id(handle, i, &value);
  699. if (err) printf(" %s = error reading value", model_info->registers[i].name);
  700. else {
  701. printf(" %s = ", model_info->registers[i].name);
  702. printf(format, value);
  703. }
  704. printf(" [");
  705. printf(format, model_info->registers[i].defvalue);
  706. printf("]");
  707. printf("\n");
  708. }
  709. }
  710. } else {
  711. printf("No registers");
  712. }
  713. printf("\n");
  714. }
  715. return 0;
  716. }
  717. #define WRITE_REGVAL(buf, n, access, o) {\
  718. uint##access##_t tbuf[n]; \
  719. for (i = 0; i < n; i++) { \
  720. tbuf[i] = (uint##access##_t)buf[i]; \
  721. } \
  722. fwrite(tbuf, access/8, n, o); \
  723. }
  724. int ReadRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, size_t n, FILE *o) {
  725. int err;
  726. int i;
  727. pcilib_register_bank_description_t *banks = model_info->banks;
  728. pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank);
  729. if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
  730. if (bank) Error("Invalid register bank is specified (%s)", bank);
  731. else Error("Register bank should be specified");
  732. }
  733. int access = banks[bank_id].access / 8;
  734. int size = n * abs(access);
  735. int block_width, blocks_per_line;
  736. int numbers_per_block, numbers_per_line;
  737. numbers_per_block = BLOCK_SIZE / access;
  738. block_width = numbers_per_block * ((access * 2) + SEPARATOR_WIDTH);
  739. blocks_per_line = (LINE_WIDTH - 6) / (block_width + BLOCK_SEPARATOR_WIDTH);
  740. if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
  741. numbers_per_line = blocks_per_line * numbers_per_block;
  742. pcilib_register_value_t buf[n];
  743. err = pcilib_read_register_space(handle, bank, addr, n, buf);
  744. if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
  745. if (o) {
  746. printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access));
  747. switch (access) {
  748. case 1: WRITE_REGVAL(buf, n, 8, o) break;
  749. case 2: WRITE_REGVAL(buf, n, 16, o) break;
  750. case 4: WRITE_REGVAL(buf, n, 32, o) break;
  751. case 8: WRITE_REGVAL(buf, n, 64, o) break;
  752. }
  753. } else {
  754. for (i = 0; i < n; i++) {
  755. if (i) {
  756. if (i%numbers_per_line == 0) printf("\n");
  757. else {
  758. printf("%*s", SEPARATOR_WIDTH, "");
  759. if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, "");
  760. }
  761. }
  762. if (i%numbers_per_line == 0) printf("%4lx: ", addr + i);
  763. printf("%0*lx", access * 2, (unsigned long)buf[i]);
  764. }
  765. printf("\n\n");
  766. }
  767. return 0;
  768. }
  769. int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data) {
  770. int read_back = 0;
  771. void *buf, *check;
  772. int res, i, err;
  773. int size = n * abs(access);
  774. size_t ret;
  775. pcilib_dma_engine_t dmaid;
  776. err = posix_memalign( (void**)&buf, 256, size );
  777. if (!err) err = posix_memalign( (void**)&check, 256, size );
  778. if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
  779. for (i = 0; i < n; i++) {
  780. switch (access) {
  781. case 1: res = sscanf(data[i], "%hhx", ((uint8_t*)buf)+i); break;
  782. case 2: res = sscanf(data[i], "%hx", ((uint16_t*)buf)+i); break;
  783. case 4: res = sscanf(data[i], "%x", ((uint32_t*)buf)+i); break;
  784. case 8: res = sscanf(data[i], "%lx", ((uint64_t*)buf)+i); break;
  785. }
  786. if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
  787. }
  788. if (endianess) pcilib_swap(buf, buf, abs(access), n);
  789. switch (mode) {
  790. case ACCESS_DMA:
  791. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
  792. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
  793. err = pcilib_write_dma(handle, dmaid, addr, size, buf, &ret);
  794. if ((err)||(ret != size)) {
  795. if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout writting the data to DMA");
  796. else if (err) Error("DMA engine returned a error while writing the data");
  797. else if (!ret) Error("No data is written by DMA engine");
  798. else Error("Only %lu bytes of %lu is written by DMA engine", ret, size);
  799. }
  800. break;
  801. case ACCESS_FIFO:
  802. pcilib_write_fifo(handle, bar, addr, access, n, buf);
  803. break;
  804. default:
  805. pcilib_write(handle, bar, addr, size, buf);
  806. pcilib_read(handle, bar, addr, size, check);
  807. read_back = 1;
  808. }
  809. if ((read_back)&&(memcmp(buf, check, size))) {
  810. printf("Write failed: the data written and read differ, the foolowing is read back:\n");
  811. if (endianess) pcilib_swap(check, check, abs(access), n);
  812. ReadData(handle, mode, 0, dma, bar, addr, n, access, endianess, (size_t)-1, NULL);
  813. exit(-1);
  814. }
  815. free(check);
  816. free(buf);
  817. return 0;
  818. }
  819. int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, size_t n, char ** data) {
  820. pcilib_register_value_t *buf, *check;
  821. int res, i, err;
  822. unsigned long value;
  823. int size = n * sizeof(pcilib_register_value_t);
  824. err = posix_memalign( (void**)&buf, 256, size );
  825. if (!err) err = posix_memalign( (void**)&check, 256, size );
  826. if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
  827. for (i = 0; i < n; i++) {
  828. res = sscanf(data[i], "%lx", &value);
  829. if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
  830. buf[i] = value;
  831. }
  832. err = pcilib_write_register_space(handle, bank, addr, n, buf);
  833. if (err) Error("Error writting register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
  834. err = pcilib_read_register_space(handle, bank, addr, n, check);
  835. if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
  836. if (memcmp(buf, check, size)) {
  837. printf("Write failed: the data written and read differ, the foolowing is read back:\n");
  838. ReadRegisterRange(handle, model_info, bank, addr, n, NULL);
  839. exit(-1);
  840. }
  841. free(check);
  842. free(buf);
  843. return 0;
  844. }
  845. int WriteRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg, char ** data) {
  846. int err;
  847. int i;
  848. unsigned long val;
  849. pcilib_register_value_t value;
  850. const char *format;
  851. pcilib_register_t regid = pcilib_find_register(handle, bank, reg);
  852. if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected");
  853. /*
  854. pcilib_register_bank_t bank_id;
  855. pcilib_register_bank_addr_t bank_addr;
  856. bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank);
  857. if (bank_id == PCILIB_REGISTER_BANK_INVALID) Error("Can't find bank of the register (%s)", reg);
  858. format = model_info->banks[bank_id].format;
  859. if (!format) format = "%lu";
  860. */
  861. if (isnumber(*data)) {
  862. if (sscanf(*data, "%li", &val) != 1) {
  863. Error("Can't parse data value (%s) is not valid decimal number", *data);
  864. }
  865. format = "%li";
  866. } else if (isxnumber(*data)) {
  867. if (sscanf(*data, "%lx", &val) != 1) {
  868. Error("Can't parse data value (%s) is not valid decimal number", *data);
  869. }
  870. format = "0x%lx";
  871. } else {
  872. Error("Can't parse data value (%s) is not valid decimal number", *data);
  873. }
  874. value = val;
  875. err = pcilib_write_register(handle, bank, reg, value);
  876. if (err) Error("Error writting register %s\n", reg);
  877. if ((model_info->registers[regid].mode&PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) {
  878. err = pcilib_read_register(handle, bank, reg, &value);
  879. if (err) Error("Error reading back register %s for verification\n", reg);
  880. if (val != value) {
  881. Error("Failed to write register %s: %lu is written and %lu is read back", reg, val, value);
  882. } else {
  883. printf("%s = ", reg);
  884. printf(format, value);
  885. printf("\n");
  886. }
  887. } else {
  888. printf("%s is written\n ", reg);
  889. }
  890. return 0;
  891. }
  892. typedef struct {
  893. pcilib_t *handle;
  894. pcilib_event_t event;
  895. pcilib_event_data_type_t data;
  896. FILE *output;
  897. size_t run_time;
  898. size_t trigger_time;
  899. int run_flag;
  900. } GRABContext;
  901. int GrabCallback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) {
  902. /* int err;
  903. void *data;
  904. size_t size, written;
  905. GRABContext *ctx = (GRABContext*)user;
  906. pcilib_t *handle = ctx->handle;
  907. FILE *o = ctx->output;
  908. data = pcilib_get_data(handle, ctx->event, ctx->data, &size);
  909. if (!data) Error("Internal Error: No data is provided to event callback");
  910. if (o) printf("Writting %zu bytes into file...\n", size);
  911. else o = stdout;
  912. written = fwrite(data, 1, size, o);
  913. if (written != size) {
  914. if (written > 0) Error("Write failed, only %z bytes out of %z are stored", written, size);
  915. else Error("Write failed");
  916. }
  917. pcilib_return_data(handle, ctx->event, data);
  918. */
  919. printf("data callback: %lu\n", event_id);
  920. }
  921. int raw_data(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event_flags_t flags, size_t size, void *data, void *user) {
  922. // printf("%i\n", event_id);
  923. }
  924. void *Trigger(void *user) {
  925. GRABContext *ctx = (GRABContext*)user;
  926. pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL);
  927. usleep(3000);
  928. pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL);
  929. return NULL;
  930. }
  931. int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, const char *data_type, size_t num, size_t run_time, size_t trigger_time, PARTITION partition, FORMAT format, size_t buffer_size, FILE *ofile) {
  932. int err;
  933. GRABContext ctx;
  934. void *data = NULL;
  935. size_t size, written;
  936. pthread_t trigger_thread;
  937. ctx.handle = handle;
  938. ctx.output = ofile;
  939. ctx.event = PCILIB_EVENT0;
  940. ctx.run_time = run_time;
  941. ctx.trigger_time = trigger_time;
  942. ctx.run_flag = 1;
  943. // ignoring event for now
  944. pcilib_configure_autostop(handle, 2, 1000000);//PCILIB_TIMEOUT_TRIGGER);
  945. pcilib_configure_rawdata_callback(handle, &raw_data, NULL);
  946. err = pcilib_start(handle, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
  947. if (err) Error("Failed to start event engine, error %i", err);
  948. if (pthread_create(&trigger_thread, NULL, Trigger, (void*)&ctx))
  949. Error("Error starting trigger thread");
  950. // sleep(1);
  951. err = pcilib_stream(handle, &GrabCallback, &ctx);
  952. if (err) Error("Error streaming events, error %i", err);
  953. pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT);
  954. /*
  955. err = pcilib_grab(handle, PCILIB_EVENTS_ALL, &size, &data, PCILIB_TIMEOUT_TRIGGER);
  956. if (err) {
  957. Error("Grabbing event is failed");
  958. }
  959. */
  960. ctx.run_flag = 0;
  961. pthread_join(trigger_thread, NULL);
  962. return 0;
  963. }
  964. /*
  965. int Trigger(pcilib_t *handle, const char *event, size_t triggers, size_t run_time, size_t trigger_time) {
  966. //
  967. }
  968. */
  969. int StartStopDMA(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, int start) {
  970. int err;
  971. pcilib_dma_engine_t dmaid;
  972. if (dma == PCILIB_DMA_ENGINE_ADDR_INVALID) {
  973. const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle);
  974. if (start) Error("DMA engine should be specified");
  975. for (dmaid = 0; dma_info->engines[dmaid]; dmaid++) {
  976. err = pcilib_start_dma(handle, dmaid, 0);
  977. if (err) Error("Error starting DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr);
  978. err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
  979. if (err) Error("Error stopping DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr);
  980. }
  981. return 0;
  982. }
  983. if (dma_direction&PCILIB_DMA_FROM_DEVICE) {
  984. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
  985. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (C2S %lu) is specified", dma);
  986. if (start) {
  987. err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
  988. if (err) Error("Error starting DMA engine (C2S %lu)", dma);
  989. } else {
  990. err = pcilib_start_dma(handle, dmaid, 0);
  991. if (err) Error("Error starting DMA engine (C2S %lu)", dma);
  992. err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
  993. if (err) Error("Error stopping DMA engine (C2S %lu)", dma);
  994. }
  995. }
  996. if (dma_direction&PCILIB_DMA_TO_DEVICE) {
  997. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
  998. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (S2C %lu) is specified", dma);
  999. if (start) {
  1000. err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
  1001. if (err) Error("Error starting DMA engine (S2C %lu)", dma);
  1002. } else {
  1003. err = pcilib_start_dma(handle, dmaid, 0);
  1004. if (err) Error("Error starting DMA engine (S2C %lu)", dma);
  1005. err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
  1006. if (err) Error("Error stopping DMA engine (S2C %lu)", dma);
  1007. }
  1008. }
  1009. return 0;
  1010. }
  1011. typedef struct {
  1012. unsigned long use;
  1013. int referenced;
  1014. int hw_lock;
  1015. int reusable;
  1016. int persistent;
  1017. int open;
  1018. size_t count;
  1019. size_t size;
  1020. } kmem_use_info_t;
  1021. #define MAX_USES 64
  1022. size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, unsigned long use) {
  1023. size_t i, n = *n_uses;
  1024. if (uses[n - 1].use == use) return n - 1;
  1025. for (i = 1; i < (n - 1); i++) {
  1026. if (uses[i].use == use) return i;
  1027. }
  1028. if (n == MAX_USES) return 0;
  1029. uses[n].use = use;
  1030. return (*n_uses)++;
  1031. }
  1032. char *PrintSize(char *str, size_t size) {
  1033. if (size >= 1073741824) sprintf(str, "%.1lf GB", 1.*size / 1073741824);
  1034. else if (size >= 1048576) sprintf(str, "%.1lf MB", 1.*size / 1048576);
  1035. else if (size >= 1024) sprintf(str, "%lu KB", size / 1024);
  1036. else sprintf(str, "%lu B ", size);
  1037. return str;
  1038. }
  1039. int ListKMEM(pcilib_t *handle, const char *device) {
  1040. DIR *dir;
  1041. struct dirent *entry;
  1042. const char *pos;
  1043. char sysdir[256];
  1044. char fname[256];
  1045. char info[256];
  1046. char stmp[256];
  1047. size_t useid, i, n_uses = 1; // Use 0 is for others
  1048. kmem_use_info_t uses[MAX_USES];
  1049. memset(uses, 0, sizeof(uses));
  1050. pos = strrchr(device, '/');
  1051. if (pos) ++pos;
  1052. else pos = device;
  1053. snprintf(sysdir, 255, "/sys/class/fpga/%s", pos);
  1054. dir = opendir(sysdir);
  1055. if (!dir) Error("Can't open directory (%s)", sysdir);
  1056. while ((entry = readdir(dir)) != NULL) {
  1057. FILE *f;
  1058. unsigned long use;
  1059. unsigned long size;
  1060. unsigned long refs;
  1061. unsigned long mode;
  1062. unsigned long hwref;
  1063. if (strncmp(entry->d_name, "kbuf", 4)) continue;
  1064. if (!isnumber(entry->d_name+4)) continue;
  1065. snprintf(fname, 255, "%s/%s", sysdir, entry->d_name);
  1066. f = fopen(fname, "r");
  1067. if (!f) Error("Can't access file (%s)", fname);
  1068. while(!feof(f)) {
  1069. fgets(info, 256, f);
  1070. if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16);
  1071. if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
  1072. if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
  1073. if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16);
  1074. if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
  1075. }
  1076. fclose(f);
  1077. useid = FindUse(&n_uses, uses, use);
  1078. uses[useid].count++;
  1079. uses[useid].size += size;
  1080. if (refs) uses[useid].referenced = 1;
  1081. if (hwref) uses[useid].hw_lock = 1;
  1082. if (mode&KMEM_MODE_REUSABLE) uses[useid].reusable = 1;
  1083. if (mode&KMEM_MODE_PERSISTENT) uses[useid].persistent = 1;
  1084. if (mode&KMEM_MODE_COUNT) uses[useid].open = 1;
  1085. }
  1086. closedir(dir);
  1087. if ((n_uses == 1)&&(uses[0].count == 0)) {
  1088. printf("No kernel memory is allocated\n");
  1089. return 0;
  1090. }
  1091. printf("Use Type Count Total Size REF Mode \n");
  1092. printf("--------------------------------------------------------------------------------\n");
  1093. for (useid = 0; useid < n_uses; useid++) {
  1094. if (useid + 1 == n_uses) {
  1095. if (!uses[0].count) continue;
  1096. i = 0;
  1097. } else i = useid + 1;
  1098. printf("%08lx ", uses[i].use);
  1099. if (!i) printf("All Others ");
  1100. else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
  1101. else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
  1102. else printf (" ", uses[i].use);
  1103. printf(" ");
  1104. printf("% 6lu", uses[i].count);
  1105. printf(" ");
  1106. printf("% 10s", PrintSize(stmp, uses[i].size));
  1107. printf(" ");
  1108. if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW");
  1109. else if (uses[i].referenced) printf(" SW");
  1110. else if (uses[i].hw_lock) printf("HW ");
  1111. else printf(" - ");
  1112. printf(" ");
  1113. if (uses[i].persistent) printf("Persistent");
  1114. else if (uses[i].open) printf("Open ");
  1115. else if (uses[i].reusable) printf("Reusable ");
  1116. else printf("Closed ");
  1117. printf("\n");
  1118. }
  1119. printf("--------------------------------------------------------------------------------\n");
  1120. printf("REF - Software/Hardware Reference, MODE - Reusable/Persistent/Open\n");
  1121. return 0;
  1122. }
  1123. int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t use, size_t block, size_t max_size, FILE *o) {
  1124. void *data;
  1125. size_t size;
  1126. pcilib_kmem_handle_t *kbuf;
  1127. kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, use, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
  1128. if (!kbuf) {
  1129. printf("The specified kernel buffer is not allocated\n");
  1130. return 0;
  1131. }
  1132. data = pcilib_kmem_get_block_ua(handle, kbuf, block);
  1133. if (data) {
  1134. size = pcilib_kmem_get_block_size(handle, kbuf, block);
  1135. if ((max_size)&&(size > max_size)) size = max_size;
  1136. fwrite(data, 1, size, o?o:stdout);
  1137. } else {
  1138. printf("The specified block is not existing\n");
  1139. }
  1140. pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
  1141. }
  1142. int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
  1143. int err;
  1144. int i;
  1145. unsigned long useid;
  1146. pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE;
  1147. if (force) flags |= PCILIB_KMEM_FLAG_FORCE; // this will ignore mmap locks as well.
  1148. if (!strcasecmp(use, "dma")) {
  1149. for (i = 0; i < PCILIB_MAX_DMA_ENGINES; i++) {
  1150. err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, i), flags);
  1151. if (err) Error("Error cleaning DMA%i C2S Ring buffer", i);
  1152. err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x80|i), flags);
  1153. if (err) Error("Error cleaning DMA%i S2C Ring buffer", i);
  1154. err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, i), flags);
  1155. if (err) Error("Error cleaning DMA%i C2S Page buffers", i);
  1156. err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x80|i), flags);
  1157. if (err) Error("Error cleaning DMA%i S2C Page buffers", i);
  1158. }
  1159. return 0;
  1160. }
  1161. if ((!isxnumber(use))||(sscanf(use, "%lx", &useid) != 1)) Error("Invalid use (%s) is specified", use);
  1162. err = pcilib_clean_kernel_memory(handle, useid, flags);
  1163. if (err) Error("Error cleaning kernel buffers for use (0x%lx)", useid);
  1164. return 0;
  1165. }
  1166. int ListDMA(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info) {
  1167. int err;
  1168. DIR *dir;
  1169. struct dirent *entry;
  1170. const char *pos;
  1171. char sysdir[256];
  1172. char fname[256];
  1173. char info[256];
  1174. char stmp[256];
  1175. pcilib_dma_engine_t dmaid;
  1176. pcilib_dma_engine_status_t status;
  1177. pos = strrchr(device, '/');
  1178. if (pos) ++pos;
  1179. else pos = device;
  1180. snprintf(sysdir, 255, "/sys/class/fpga/%s", pos);
  1181. dir = opendir(sysdir);
  1182. if (!dir) Error("Can't open directory (%s)", sysdir);
  1183. printf("DMA Engine Status Total Size Buffer Ring (1st used - 1st free)\n");
  1184. printf("--------------------------------------------------------------------------------\n");
  1185. while ((entry = readdir(dir)) != NULL) {
  1186. FILE *f;
  1187. unsigned long use;
  1188. unsigned long size;
  1189. unsigned long refs;
  1190. unsigned long mode;
  1191. unsigned long hwref;
  1192. if (strncmp(entry->d_name, "kbuf", 4)) continue;
  1193. if (!isnumber(entry->d_name+4)) continue;
  1194. snprintf(fname, 255, "%s/%s", sysdir, entry->d_name);
  1195. f = fopen(fname, "r");
  1196. if (!f) Error("Can't access file (%s)", fname);
  1197. while(!feof(f)) {
  1198. fgets(info, 256, f);
  1199. if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16);
  1200. if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
  1201. if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
  1202. if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16);
  1203. if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
  1204. }
  1205. fclose(f);
  1206. if ((mode&(KMEM_MODE_REUSABLE|KMEM_MODE_PERSISTENT|KMEM_MODE_COUNT)) == 0) continue; // closed
  1207. if ((use >> 16) != PCILIB_KMEM_USE_DMA_RING) continue;
  1208. if (use&0x80) {
  1209. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, use&0x7F);
  1210. } else {
  1211. dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, use&0x7F);
  1212. }
  1213. if (dmaid == PCILIB_DMA_ENGINE_INVALID) continue;
  1214. printf("DMA%u %s ", use&0x7F, (use&0x80)?"S2C":"C2S");
  1215. err = pcilib_start_dma(handle, dmaid, 0);
  1216. if (err) {
  1217. printf("-- Wrong state, start is failed\n");
  1218. continue;
  1219. }
  1220. err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
  1221. if (err) {
  1222. printf("-- Wrong state, failed to obtain status\n");
  1223. pcilib_stop_dma(handle, dmaid, 0);
  1224. continue;
  1225. }
  1226. pcilib_stop_dma(handle, dmaid, 0);
  1227. if (status.started) printf("S");
  1228. else printf(" ");
  1229. if (status.ring_head == status.ring_tail) printf(" ");
  1230. else printf("D");
  1231. printf(" ");
  1232. printf("% 10s", PrintSize(stmp, status.ring_size * status.buffer_size));
  1233. printf(" ");
  1234. printf("%zu - %zu (of %zu)", status.ring_tail, status.ring_head, status.ring_size);
  1235. printf("\n");
  1236. }
  1237. closedir(dir);
  1238. printf("--------------------------------------------------------------------------------\n");
  1239. printf("S - Started, D - Data in buffers\n");
  1240. return 0;
  1241. }
  1242. int ListBuffers(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction) {
  1243. int err;
  1244. size_t i;
  1245. pcilib_dma_engine_t dmaid;
  1246. pcilib_dma_engine_status_t status;
  1247. pcilib_dma_buffer_status_t *buffer;
  1248. char stmp[256];
  1249. dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma);
  1250. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found");
  1251. err = pcilib_start_dma(handle, dmaid, 0);
  1252. if (err) Error("Error starting the specified DMA engine");
  1253. err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
  1254. if (err) Error("Failed to obtain status of the specified DMA engine");
  1255. buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t));
  1256. if (!buffer) Error("Failed to allocate memory for status buffer");
  1257. err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer);
  1258. if (err) Error("Failed to obtain extended status of the specified DMA engine");
  1259. printf("Buffer Status Total Size \n");
  1260. printf("--------------------------------------------------------------------------------\n");
  1261. for (i = 0; i < status.ring_size; i++) {
  1262. printf("%8zu ", i);
  1263. printf("%c%c %c%c ", buffer[i].used?'U':' ', buffer[i].error?'E':' ', buffer[i].first?'F':' ', buffer[i].last?'L':' ');
  1264. printf("% 10s", PrintSize(stmp, buffer[i].size));
  1265. printf("\n");
  1266. }
  1267. printf("--------------------------------------------------------------------------------\n");
  1268. printf("U - Used, E - Error, F - First block, L - Last Block\n");
  1269. free(buffer);
  1270. pcilib_stop_dma(handle, dmaid, 0);
  1271. }
  1272. int ReadBuffer(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, size_t block, FILE *o) {
  1273. int err;
  1274. size_t i;
  1275. pcilib_dma_engine_t dmaid;
  1276. pcilib_dma_engine_status_t status;
  1277. pcilib_dma_buffer_status_t *buffer;
  1278. size_t size;
  1279. char stmp[256];
  1280. dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma);
  1281. if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found");
  1282. err = pcilib_start_dma(handle, dmaid, 0);
  1283. if (err) Error("Error starting the specified DMA engine");
  1284. err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
  1285. if (err) Error("Failed to obtain status of the specified DMA engine");
  1286. buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t));
  1287. if (!buffer) Error("Failed to allocate memory for status buffer");
  1288. err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer);
  1289. if (err) Error("Failed to obtain extended status of the specified DMA engine");
  1290. if (block == (size_t)-1) {
  1291. // get current
  1292. }
  1293. size = buffer[block].size;
  1294. free(buffer);
  1295. pcilib_stop_dma(handle, dmaid, 0);
  1296. // printf("%i %i\n", dma, buffer);
  1297. // printf("%lx\n", ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16));
  1298. return ReadKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, o);
  1299. }
  1300. int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source, pcilib_timeout_t timeout) {
  1301. int err;
  1302. size_t count;
  1303. err = pcilib_enable_irq(handle, PCILIB_EVENT_IRQ, 0);
  1304. if (err) Error("Error enabling IRQs");
  1305. err = pcilib_wait_irq(handle, irq_source, timeout, &count);
  1306. if (err) {
  1307. if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout waiting for IRQ");
  1308. else Error("Error waiting for IRQ");
  1309. }
  1310. return 0;
  1311. }
  1312. int main(int argc, char **argv) {
  1313. int i;
  1314. long itmp;
  1315. unsigned long utmp;
  1316. size_t ztmp;
  1317. unsigned char c;
  1318. const char *stmp;
  1319. const char *num_offset;
  1320. int details = 0;
  1321. int quiete = 0;
  1322. int force = 0;
  1323. pcilib_model_t model = PCILIB_MODEL_DETECT;
  1324. pcilib_model_description_t *model_info;
  1325. MODE mode = MODE_INVALID;
  1326. GRAB_MODE grab_mode = 0;
  1327. size_t trigger_time = 0;
  1328. size_t run_time = 0;
  1329. size_t buffer = 0;
  1330. FORMAT format = FORMAT_RAW;
  1331. PARTITION partition = PARTITION_UNKNOWN;
  1332. FLAGS flags = 0;
  1333. const char *type = NULL;
  1334. ACCESS_MODE amode = ACCESS_BAR;
  1335. const char *fpga_device = DEFAULT_FPGA_DEVICE;
  1336. pcilib_bar_t bar = PCILIB_BAR_DETECT;
  1337. const char *addr = NULL;
  1338. const char *reg = NULL;
  1339. const char *bank = NULL;
  1340. char **data = NULL;
  1341. const char *event = NULL;
  1342. const char *data_type = NULL;
  1343. const char *dma_channel = NULL;
  1344. const char *use = NULL;
  1345. pcilib_kmem_use_t use_id;
  1346. size_t block = 0;
  1347. pcilib_irq_hw_source_t irq_source;
  1348. pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
  1349. pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID;
  1350. uintptr_t start = -1;
  1351. size_t size = 1;
  1352. access_t access = 4;
  1353. int skip = 0;
  1354. int endianess = 0;
  1355. size_t timeout = 0;
  1356. const char *output = NULL;
  1357. FILE *ofile = NULL;
  1358. size_t iterations = BENCHMARK_ITERATIONS;
  1359. pcilib_t *handle;
  1360. int size_set = 0;
  1361. int timeout_set = 0;
  1362. while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) {
  1363. extern int optind;
  1364. switch (c) {
  1365. case OPT_HELP:
  1366. Usage(argc, argv, NULL);
  1367. break;
  1368. case OPT_INFO:
  1369. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1370. mode = MODE_INFO;
  1371. break;
  1372. case OPT_LIST:
  1373. if (mode == MODE_LIST) details++;
  1374. else if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1375. mode = MODE_LIST;
  1376. break;
  1377. case OPT_RESET:
  1378. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1379. mode = MODE_RESET;
  1380. break;
  1381. case OPT_BENCHMARK:
  1382. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1383. mode = MODE_BENCHMARK;
  1384. if (optarg) addr = optarg;
  1385. else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
  1386. break;
  1387. case OPT_READ:
  1388. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1389. mode = MODE_READ;
  1390. if (optarg) addr = optarg;
  1391. else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
  1392. break;
  1393. case OPT_WRITE:
  1394. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1395. mode = MODE_WRITE;
  1396. if (optarg) addr = optarg;
  1397. else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
  1398. break;
  1399. case OPT_GRAB:
  1400. if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_GRAB))) Usage(argc, argv, "Multiple operations are not supported");
  1401. mode = MODE_GRAB;
  1402. grab_mode |= GRAB_MODE_GRAB;
  1403. stmp = NULL;
  1404. if (optarg) stmp = optarg;
  1405. else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++];
  1406. if (stmp) {
  1407. if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event");
  1408. event = stmp;
  1409. }
  1410. break;
  1411. case OPT_TRIGGER:
  1412. if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_TRIGGER))) Usage(argc, argv, "Multiple operations are not supported");
  1413. mode = MODE_GRAB;
  1414. grab_mode |= GRAB_MODE_TRIGGER;
  1415. stmp = NULL;
  1416. if (optarg) stmp = optarg;
  1417. else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++];
  1418. if (stmp) {
  1419. if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event");
  1420. event = stmp;
  1421. }
  1422. break;
  1423. case OPT_LIST_DMA:
  1424. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1425. mode = MODE_LIST_DMA;
  1426. break;
  1427. case OPT_LIST_DMA_BUFFERS:
  1428. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1429. mode = MODE_LIST_DMA_BUFFERS;
  1430. dma_channel = optarg;
  1431. break;
  1432. case OPT_READ_DMA_BUFFER:
  1433. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1434. mode = MODE_READ_DMA_BUFFER;
  1435. num_offset = strchr(optarg, ':');
  1436. if (num_offset) {
  1437. if (sscanf(num_offset + 1, "%zu", &block) != 1)
  1438. Usage(argc, argv, "Invalid buffer is specified (%s)", num_offset + 1);
  1439. *(char*)num_offset = 0;
  1440. } else block = (size_t)-1;
  1441. dma_channel = optarg;
  1442. break;
  1443. case OPT_START_DMA:
  1444. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1445. mode = MODE_START_DMA;
  1446. if (optarg) dma_channel = optarg;
  1447. else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
  1448. break;
  1449. case OPT_STOP_DMA:
  1450. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1451. mode = MODE_STOP_DMA;
  1452. if (optarg) dma_channel = optarg;
  1453. else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
  1454. break;
  1455. case OPT_WAIT_IRQ:
  1456. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1457. mode = MODE_WAIT_IRQ;
  1458. if (optarg) num_offset = optarg;
  1459. else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
  1460. if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
  1461. Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
  1462. irq_source = itmp;
  1463. break;
  1464. case OPT_LIST_KMEM:
  1465. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1466. mode = MODE_LIST_KMEM;
  1467. break;
  1468. case OPT_READ_KMEM:
  1469. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1470. mode = MODE_READ_KMEM;
  1471. num_offset = strchr(optarg, ':');
  1472. if (num_offset) {
  1473. if (sscanf(num_offset + 1, "%zu", &block) != 1)
  1474. Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
  1475. *(char*)num_offset = 0;
  1476. }
  1477. if (sscanf(optarg, "%lx", &utmp) != 1)
  1478. Usage(argc, argv, "Invalid USE number is specified (%s)", optarg);
  1479. if (!utmp)
  1480. Usage(argc, argv, "Can't read buffer with the unspecific use (use number is 0)");
  1481. use_id = utmp;
  1482. break;
  1483. case OPT_FREE_KMEM:
  1484. if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
  1485. mode = MODE_FREE_KMEM;
  1486. if (optarg) use = optarg;
  1487. else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++];
  1488. break;
  1489. case OPT_DEVICE:
  1490. fpga_device = optarg;
  1491. break;
  1492. case OPT_MODEL:
  1493. if (!strcasecmp(optarg, "pci")) model = PCILIB_MODEL_PCI;
  1494. else if (!strcasecmp(optarg, "ipecamera")) model = PCILIB_MODEL_IPECAMERA;
  1495. else Usage(argc, argv, "Invalid memory model (%s) is specified", optarg);
  1496. break;
  1497. case OPT_BAR:
  1498. bank = optarg;
  1499. // if ((sscanf(optarg,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
  1500. // else bar = itmp;
  1501. break;
  1502. case OPT_ACCESS:
  1503. if (!strncasecmp(optarg, "fifo", 4)) {
  1504. type = "fifo";
  1505. num_offset = optarg + 4;
  1506. amode = ACCESS_FIFO;
  1507. } else if (!strncasecmp(optarg, "dma", 3)) {
  1508. type = "dma";
  1509. num_offset = optarg + 3;
  1510. amode = ACCESS_DMA;
  1511. } else if (!strncasecmp(optarg, "bar", 3)) {
  1512. type = "plain";
  1513. num_offset = optarg + 3;
  1514. amode = ACCESS_BAR;
  1515. } else if (!strncasecmp(optarg, "plain", 5)) {
  1516. type = "plain";
  1517. num_offset = optarg + 5;
  1518. amode = ACCESS_BAR;
  1519. } else {
  1520. num_offset = optarg;
  1521. }
  1522. if (*num_offset) {
  1523. if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
  1524. Usage(argc, argv, "Invalid access type (%s) is specified", optarg);
  1525. switch (itmp) {
  1526. case 8: access = 1; break;
  1527. case 16: access = 2; break;
  1528. case 32: access = 4; break;
  1529. case 64: access = 8; break;
  1530. default: Usage(argc, argv, "Invalid data width (%s) is specified", num_offset);
  1531. }
  1532. }
  1533. break;
  1534. case OPT_SIZE:
  1535. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &size) != 1))
  1536. if (strcasecmp(optarg, "unlimited"))
  1537. Usage(argc, argv, "Invalid size is specified (%s)", optarg);
  1538. else
  1539. size = (size_t)-1;
  1540. size_set = 1;
  1541. break;
  1542. case OPT_ENDIANESS:
  1543. if ((*optarg == 'b')||(*optarg == 'B')) {
  1544. if (ntohs(1) == 1) endianess = 0;
  1545. else endianess = 1;
  1546. } else if ((*optarg == 'l')||(*optarg == 'L')) {
  1547. if (ntohs(1) == 1) endianess = 1;
  1548. else endianess = 0;
  1549. } else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);
  1550. break;
  1551. case OPT_TIMEOUT:
  1552. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1))
  1553. Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
  1554. timeout_set = 1;
  1555. break;
  1556. case OPT_OUTPUT:
  1557. output = optarg;
  1558. break;
  1559. case OPT_ITERATIONS:
  1560. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &iterations) != 1))
  1561. Usage(argc, argv, "Invalid number of iterations is specified (%s)", optarg);
  1562. break;
  1563. case OPT_EVENT:
  1564. event = optarg;
  1565. break;
  1566. case OPT_DATA_TYPE:
  1567. data_type = optarg;
  1568. break;
  1569. case OPT_RUN_TIME:
  1570. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &run_time) != 1))
  1571. Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
  1572. break;
  1573. case OPT_TRIGGER_TIME:
  1574. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1))
  1575. Usage(argc, argv, "Invalid trigger-time is specified (%s)", optarg);
  1576. break;
  1577. case OPT_TRIGGER_RATE:
  1578. if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &ztmp) != 1))
  1579. Usage(argc, argv, "Invalid trigger-rate is specified (%s)", optarg);
  1580. trigger_time = 1000000 / ztmp + (1000000 % ztmp)?1:0;
  1581. break;
  1582. case OPT_BUFFER:
  1583. if (optarg) num_offset = optarg;
  1584. else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
  1585. else num_offset = NULL;
  1586. if (num_offset) {
  1587. if ((!isnumber(num_offset))||(sscanf(num_offset, "%zu", &buffer) != 1))
  1588. Usage(argc, argv, "Invalid buffer size is specified (%s)", num_offset);
  1589. buffer *= 1024 * 1024;
  1590. } else {
  1591. buffer = get_free_memory();
  1592. if (buffer < 256) Error("Not enough free memory (%lz MB) for buffering", buffer / 1024 / 1024);
  1593. buffer -= 128 + buffer/16;
  1594. }
  1595. break;
  1596. case OPT_FORMAT:
  1597. if (!strcasecmp(optarg, "add_header")) format = FORMAT_HEADER;
  1598. else if (!strcasecmp(optarg, "ringfs")) format = FORMAT_RINGFS;
  1599. else if (strcasecmp(optarg, "raw")) Error("Invalid format (%s) is specified", optarg);
  1600. break;
  1601. case OPT_QUIETE:
  1602. quiete = 1;
  1603. break;
  1604. case OPT_FORCE:
  1605. force = 1;
  1606. break;
  1607. case OPT_MULTIPACKET:
  1608. flags |= FLAG_MULTIPACKET;
  1609. break;
  1610. case OPT_WAIT:
  1611. flags |= FLAG_WAIT;
  1612. break;
  1613. default:
  1614. Usage(argc, argv, "Unknown option (%s) with argument (%s)", optarg?argv[optind-2]:argv[optind-1], optarg?optarg:"(null)");
  1615. }
  1616. }
  1617. if (mode == MODE_INVALID) {
  1618. if (argc > 1) Usage(argc, argv, "Operation is not specified");
  1619. else Usage(argc, argv, NULL);
  1620. }
  1621. pcilib_set_error_handler(&Error, quiete?Silence:NULL);
  1622. handle = pcilib_open(fpga_device, model);
  1623. if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device);
  1624. model = pcilib_get_model(handle);
  1625. model_info = pcilib_get_model_description(handle);
  1626. switch (mode) {
  1627. case MODE_WRITE:
  1628. if (!addr) Usage(argc, argv, "The address is not specified");
  1629. if (((argc - optind) == 1)&&(*argv[optind] == '*')) {
  1630. int vallen = strlen(argv[optind]);
  1631. if (vallen > 1) {
  1632. data = (char**)malloc(size * (vallen + sizeof(char*)));
  1633. if (!data) Error("Error allocating memory for data array");
  1634. for (i = 0; i < size; i++) {
  1635. data[i] = ((char*)data) + size * sizeof(char*) + i * vallen;
  1636. strcpy(data[i], argv[optind] + 1);
  1637. }
  1638. } else {
  1639. data = (char**)malloc(size * (9 + sizeof(char*)));
  1640. if (!data) Error("Error allocating memory for data array");
  1641. for (i = 0; i < size; i++) {
  1642. data[i] = ((char*)data) + size * sizeof(char*) + i * 9;
  1643. sprintf(data[i], "%x", i);
  1644. }
  1645. }
  1646. } else if ((argc - optind) == size) data = argv + optind;
  1647. else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size);
  1648. break;
  1649. case MODE_READ:
  1650. if (!addr) {
  1651. if (model == PCILIB_MODEL_PCI) {
  1652. Usage(argc, argv, "The address is not specified");
  1653. } else ++mode;
  1654. }
  1655. break;
  1656. case MODE_START_DMA:
  1657. case MODE_STOP_DMA:
  1658. case MODE_LIST_DMA_BUFFERS:
  1659. case MODE_READ_DMA_BUFFER:
  1660. if ((dma_channel)&&(*dma_channel)) {
  1661. itmp = strlen(dma_channel) - 1;
  1662. if (dma_channel[itmp] == 'r') dma_direction = PCILIB_DMA_FROM_DEVICE;
  1663. else if (dma_channel[itmp] == 'w') dma_direction = PCILIB_DMA_TO_DEVICE;
  1664. if (dma_direction != PCILIB_DMA_BIDIRECTIONAL) itmp--;
  1665. if (strncmp(dma_channel, "dma", 3)) num_offset = dma_channel;
  1666. else {
  1667. num_offset = dma_channel + 3;
  1668. itmp -= 3;
  1669. }
  1670. if (bank) {
  1671. if (strncmp(num_offset, bank, itmp)) Usage(argc, argv, "Conflicting DMA channels are specified in mode parameter (%s) and bank parameter (%s)", dma_channel, bank);
  1672. }
  1673. if (!isnumber_n(num_offset, itmp))
  1674. Usage(argc, argv, "Invalid DMA channel (%s) is specified", dma_channel);
  1675. dma = atoi(num_offset);
  1676. }
  1677. break;
  1678. default:
  1679. if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
  1680. }
  1681. if (addr) {
  1682. if ((!strncmp(addr, "dma", 3))&&((addr[3]==0)||isnumber(addr+3))) {
  1683. if ((type)&&(amode != ACCESS_DMA)) Usage(argc, argv, "Conflicting access modes, the DMA read is requested, but access type is (%s)", type);
  1684. if (bank) {
  1685. if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting DMA channels are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank);
  1686. } else {
  1687. if (addr[3] == 0) Usage(argc, argv, "The DMA channel is not specified");
  1688. }
  1689. dma = atoi(addr + 3);
  1690. amode = ACCESS_DMA;
  1691. } else if ((!strncmp(addr, "bar", 3))&&((addr[3]==0)||isnumber(addr+3))) {
  1692. if ((type)&&(amode != ACCESS_BAR)) Usage(argc, argv, "Conflicting access modes, the plain PCI read is requested, but access type is (%s)", type);
  1693. if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting PCI bars are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank);
  1694. bar = atoi(addr + 3);
  1695. amode = ACCESS_BAR;
  1696. } else if ((isxnumber(addr))&&(sscanf(addr, "%lx", &start) == 1)) {
  1697. // check if the address in the register range
  1698. pcilib_register_range_t *ranges = model_info->ranges;
  1699. if (ranges) {
  1700. for (i = 0; ranges[i].start != ranges[i].end; i++)
  1701. if ((start >= ranges[i].start)&&(start <= ranges[i].end)) break;
  1702. // register access in plain mode
  1703. if (ranges[i].start != ranges[i].end) {
  1704. pcilib_register_bank_t regbank = pcilib_find_bank_by_addr(handle, ranges[i].bank);
  1705. if (regbank == PCILIB_REGISTER_BANK_INVALID) Error("Configuration error: register bank specified in the address range is not found");
  1706. bank = model_info->banks[regbank].name;
  1707. start += ranges[i].addr_shift;
  1708. ++mode;
  1709. }
  1710. }
  1711. } else {
  1712. if (pcilib_find_register(handle, bank, addr) == PCILIB_REGISTER_INVALID) {
  1713. Usage(argc, argv, "Invalid address (%s) is specified", addr);
  1714. } else {
  1715. reg = addr;
  1716. ++mode;
  1717. }
  1718. }
  1719. }
  1720. if (mode == MODE_GRAB) {
  1721. if (output) {
  1722. char fsname[128];
  1723. if (!get_file_fs(output, 127, fsname)) {
  1724. if (!strcmp(fsname, "ext4")) partition = PARTITION_EXT4;
  1725. else if (!strcmp(fsname, "raw")) partition = PARTITION_RAW;
  1726. }
  1727. }
  1728. }
  1729. if (mode != MODE_GRAB) {
  1730. if (size == (size_t)-1)
  1731. Usage(argc, argv, "Unlimited size is not supported in selected operation mode");
  1732. }
  1733. if ((bank)&&(amode == ACCESS_DMA)) {
  1734. if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0))
  1735. Usage(argc, argv, "Invalid DMA channel (%s) is specified", bank);
  1736. else dma = itmp;
  1737. } else if (bank) {
  1738. switch (mode) {
  1739. case MODE_BENCHMARK:
  1740. case MODE_READ:
  1741. case MODE_WRITE:
  1742. if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS))
  1743. Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
  1744. else bar = itmp;
  1745. break;
  1746. default:
  1747. if (pcilib_find_bank(handle, bank) == PCILIB_REGISTER_BANK_INVALID)
  1748. Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
  1749. }
  1750. }
  1751. if (output) {
  1752. ofile = fopen(output, "a+");
  1753. if (!ofile) {
  1754. Error("Failed to open file \"%s\"", output);
  1755. }
  1756. }
  1757. switch (mode) {
  1758. case MODE_INFO:
  1759. Info(handle, model_info);
  1760. break;
  1761. case MODE_LIST:
  1762. List(handle, model_info, bank, details);
  1763. break;
  1764. case MODE_BENCHMARK:
  1765. Benchmark(handle, amode, dma, bar, start, size_set?size:0, access, iterations);
  1766. break;
  1767. case MODE_READ:
  1768. if (amode == ACCESS_DMA) {
  1769. ReadData(handle, amode, flags, dma, bar, start, size_set?size:0, access, endianess, timeout_set?timeout:(size_t)-1, ofile);
  1770. } else if (addr) {
  1771. ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile);
  1772. } else {
  1773. Error("Address to read is not specified");
  1774. }
  1775. break;
  1776. case MODE_READ_REGISTER:
  1777. if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg);
  1778. else ReadRegisterRange(handle, model_info, bank, start, size, ofile);
  1779. break;
  1780. case MODE_WRITE:
  1781. WriteData(handle, amode, dma, bar, start, size, access, endianess, data);
  1782. break;
  1783. case MODE_WRITE_REGISTER:
  1784. if (reg) WriteRegister(handle, model_info, bank, reg, data);
  1785. else WriteRegisterRange(handle, model_info, bank, start, size, data);
  1786. break;
  1787. case MODE_RESET:
  1788. pcilib_reset(handle);
  1789. break;
  1790. case MODE_GRAB:
  1791. TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, partition, format, buffer, ofile);
  1792. break;
  1793. case MODE_LIST_DMA:
  1794. ListDMA(handle, fpga_device, model_info);
  1795. break;
  1796. case MODE_LIST_DMA_BUFFERS:
  1797. ListBuffers(handle, fpga_device, model_info, dma, dma_direction);
  1798. break;
  1799. case MODE_READ_DMA_BUFFER:
  1800. ReadBuffer(handle, fpga_device, model_info, dma, dma_direction, block, ofile);
  1801. break;
  1802. case MODE_START_DMA:
  1803. StartStopDMA(handle, model_info, dma, dma_direction, 1);
  1804. break;
  1805. case MODE_STOP_DMA:
  1806. StartStopDMA(handle, model_info, dma, dma_direction, 0);
  1807. break;
  1808. case MODE_WAIT_IRQ:
  1809. WaitIRQ(handle, model_info, irq_source, timeout);
  1810. break;
  1811. case MODE_LIST_KMEM:
  1812. ListKMEM(handle, fpga_device);
  1813. break;
  1814. case MODE_READ_KMEM:
  1815. ReadKMEM(handle, fpga_device, use_id, block, 0, ofile);
  1816. break;
  1817. case MODE_FREE_KMEM:
  1818. FreeKMEM(handle, fpga_device, use, force);
  1819. break;
  1820. }
  1821. if (ofile) fclose(ofile);
  1822. pcilib_close(handle);
  1823. if (data != argv + optind) free(data);
  1824. }