Beispiel #1
0
void polly_copyFromHostToDevice(void *HostData, PollyGPUDevicePtr *DevData,
                                long MemSize) {
  dump_function();

  CUdeviceptr CuDevData = DevData->Cuda;
  CuMemcpyHtoDFcnPtr(CuDevData, HostData, MemSize);
}
Beispiel #2
0
void polly_copyFromDeviceToHost(PollyGPUDevicePtr *DevData, void *HostData,
                                long MemSize) {
  dump_function();

  if (CuMemcpyDtoHFcnPtr(HostData, DevData->Cuda, MemSize) != CUDA_SUCCESS) {
    fprintf(stdout, "Copying results from device to host memory failed.\n");
    exit(-1);
  }
}
Beispiel #3
0
void polly_freeKernel(PollyGPUFunction *Kernel) {
  dump_function();

  if (Kernel->CudaModule)
    CuModuleUnloadFcnPtr(Kernel->CudaModule);

  if (Kernel)
    free(Kernel);
}
void
java_genericize (tree fndecl)
{
  dump_java_tree (TDI_original, fndecl);

  /* Genericize with the gimplifier.  */
  gimplify_function_tree (fndecl);

  dump_function (TDI_generic, fndecl);
}
Beispiel #5
0
void polly_freeContext(PollyGPUContext *Context) {
  dump_function();

  if (Context->Cuda) {
    CuCtxDestroyFcnPtr(Context->Cuda);
    free(Context);
  }

  dlclose(HandleCuda);
  dlclose(HandleCudaRT);
}
static void
dump_transaction_entry( void dump_function( const char *format, ... ), const transaction_entry *entry ) {
  assert( entry != NULL );
  assert( dump_function != NULL );

  dump_function( "Transaction entry %p: xid = %#x, barrier_xid = %#x, original_xid = %#x, datapath_id = %#" PRIx64 ", message = %p, "
                 "message data = %p, message length = %u, succeeded_callback = %p, succeeded_user_data = %p, failed_callback =%p, "
                 "failed_user_data = %p, expires_at = %d.%09d, completed = %d, error_received = %d, timeout = %d.",
                 entry, entry->xid, entry->barrier_xid, entry->original_xid, entry->datapath_id, entry->message,
                 entry->message != NULL ? entry->message->data : NULL, entry->message != NULL ? entry->message->length : 0,
                 entry->succeeded_callback, entry->succeeded_user_data, entry->failed_callback, entry->failed_user_data,
                 ( int ) entry->expires_at.tv_sec, ( int ) entry->expires_at.tv_nsec, entry->completed,
                 entry->error_received, entry->timeout );
}
Beispiel #7
0
PollyGPUContext *polly_initContext() {
  DebugMode = getenv("POLLY_DEBUG") != 0;

  dump_function();
  PollyGPUContext *Context;
  CUdevice Device;

  int Major = 0, Minor = 0, DeviceID = 0;
  char DeviceName[256];
  int DeviceCount = 0;

  /* Get API handles. */
  if (initialDeviceAPIs() == 0) {
    fprintf(stdout, "Getting the \"handle\" for the CUDA driver API failed.\n");
    exit(-1);
  }

  if (CuInitFcnPtr(0) != CUDA_SUCCESS) {
    fprintf(stdout, "Initializing the CUDA driver API failed.\n");
    exit(-1);
  }

  /* Get number of devices that supports CUDA. */
  CuDeviceGetCountFcnPtr(&DeviceCount);
  if (DeviceCount == 0) {
    fprintf(stdout, "There is no device supporting CUDA.\n");
    exit(-1);
  }

  CuDeviceGetFcnPtr(&Device, 0);

  /* Get compute capabilities and the device name. */
  CuDeviceComputeCapabilityFcnPtr(&Major, &Minor, Device);
  CuDeviceGetNameFcnPtr(DeviceName, 256, Device);
  debug_print("> Running on GPU device %d : %s.\n", DeviceID, DeviceName);

  /* Create context on the device. */
  Context = (PollyGPUContext *)malloc(sizeof(PollyGPUContext));
  if (Context == 0) {
    fprintf(stdout, "Allocate memory for Polly GPU context failed.\n");
    exit(-1);
  }
  CuCtxCreateFcnPtr(&(Context->Cuda), 0, Device);

  return Context;
}
Beispiel #8
0
static void compile(const char *input)
{
	ktap_closure *cl;
	char *buff;
	struct stat sb;
	int fdin;

	if (oneline_src[0] != '\0') {
		init_dummy_global_state();
		cl = ktapc_parser(oneline_src, input);
		goto dump;
	}

	fdin = open(input, O_RDONLY);
	if (fdin < 0) {
		fprintf(stderr, "open file %s failed\n", input);
		exit(-1);
	}

	if (fstat(fdin, &sb) == -1)
		handle_error("fstat failed");

	buff = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
	if (buff == MAP_FAILED)
		handle_error("mmap failed");

	init_dummy_global_state();
	cl = ktapc_parser(buff, input);

	munmap(buff, sb.st_size);
	close(fdin);

 dump:
	if (dump_bytecode) {
		dump_function(1, cl->p);
		exit(0);
	}

	/* ktapc output */
	uparm.trunk = malloc(ktap_trunk_mem_size);
	if (!uparm.trunk)
		handle_error("malloc failed");

	ktapc_dump(cl->p, ktapc_writer, NULL, 0);
}
Beispiel #9
0
void
c_genericize (tree fndecl)
{
  FILE *dump_file;
  int local_dump_flags;
  struct cgraph_node *cgn;

  /* Dump the C-specific tree IR.  */
  dump_file = dump_begin (TDI_original, &local_dump_flags);
  if (dump_file)
    {
      fprintf (dump_file, "\n;; Function %s",
	       lang_hooks.decl_printable_name (fndecl, 2));
      fprintf (dump_file, " (%s)\n",
	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
      fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
      fprintf (dump_file, "\n");

      if (local_dump_flags & TDF_RAW)
	dump_node (DECL_SAVED_TREE (fndecl),
		   TDF_SLIM | local_dump_flags, dump_file);
      else
	print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
      fprintf (dump_file, "\n");

      dump_end (TDI_original, dump_file);
    }

  /* Go ahead and gimplify for now.  */
  push_context ();
  gimplify_function_tree (fndecl);
  pop_context ();

  /* Dump the genericized tree IR.  */
  dump_function (TDI_generic, fndecl);

  /* Genericize all nested functions now.  We do things in this order so
     that items like VLA sizes are expanded properly in the context of
     the correct function.  */
  cgn = cgraph_node (fndecl);
  for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
    c_genericize (cgn->decl);
}
Beispiel #10
0
PollyGPUDevicePtr *polly_allocateMemoryForDevice(long MemSize) {
  dump_function();

  PollyGPUDevicePtr *DevData = malloc(sizeof(PollyGPUDevicePtr));

  if (DevData == 0) {
    fprintf(stdout, "Allocate memory for GPU device memory pointer failed.\n");
    exit(-1);
  }

  CUresult Res = CuMemAllocFcnPtr(&(DevData->Cuda), MemSize);

  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "Allocate memory for GPU device memory pointer failed.\n");
    exit(-1);
  }

  return DevData;
}
Beispiel #11
0
void polly_launchKernel(PollyGPUFunction *Kernel, unsigned int GridDimX,
                        unsigned int GridDimY, unsigned int BlockDimX,
                        unsigned int BlockDimY, unsigned int BlockDimZ,
                        void **Parameters) {
  dump_function();

  unsigned GridDimZ = 1;
  unsigned int SharedMemBytes = CU_SHARED_MEM_CONFIG_DEFAULT_BANK_SIZE;
  CUstream Stream = 0;
  void **Extra = 0;

  CUresult Res;
  Res = CuLaunchKernelFcnPtr(Kernel->Cuda, GridDimX, GridDimY, GridDimZ,
                             BlockDimX, BlockDimY, BlockDimZ, SharedMemBytes,
                             Stream, Parameters, Extra);
  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "Launching CUDA kernel failed.\n");
    exit(-1);
  }
}
Beispiel #12
0
/* this is a debug function used for check bytecode chunk file */
static void dump_function(int level, ktap_proto *f)
{
	int i;

	printf("\n----------------------------------------------------\n");
	printf("function %d [level %d]:\n", function_nr++, level);
	printf("linedefined: %d\n", f->linedefined);
	printf("lastlinedefined: %d\n", f->lastlinedefined);
	printf("numparams: %d\n", f->numparams);
	printf("is_vararg: %d\n", f->is_vararg);
	printf("maxstacksize: %d\n", f->maxstacksize);
	printf("source: %s\n", getstr(f->source));
	printf("sizelineinfo: %d \t", f->sizelineinfo);
	for (i = 0; i < f->sizelineinfo; i++)
		printf("%d ", f->lineinfo[i]);
	printf("\n");

	printf("sizek: %d\n", f->sizek);
	for (i = 0; i < f->sizek; i++) {
		switch(f->k[i].type) {
		case KTAP_TNIL:
			printf("\tNIL\n");
			break;
		case KTAP_TBOOLEAN:
			printf("\tBOOLEAN: ");
			printf("%d\n", f->k[i].val.b);
			break;
		case KTAP_TNUMBER:
			printf("\tTNUMBER: ");
			printf("%ld\n", f->k[i].val.n);
			break;
		case KTAP_TSHRSTR:
		case KTAP_TLNGSTR:
			printf("\tTSTRING: ");
			printf("%s\n", svalue(&(f->k[i])));
			break;
		default:
			printf("\tUnknow constant type %d: ", f->k[i].type);
			kp_showobj(NULL, &(f->k[i]));
			printf("\n");
		}
	}

	printf("sizelocvars: %d\n", f->sizelocvars);
	for (i = 0; i < f->sizelocvars; i++) {
		printf("\tlocvars: %s startpc: %d endpc: %d\n",
			getstr(f->locvars[i].varname), f->locvars[i].startpc,
			f->locvars[i].endpc);
	}

	printf("sizeupvalues: %d\n", f->sizeupvalues);
	for (i = 0; i < f->sizeupvalues; i++) {
		printf("\tname: %s instack: %d idx: %d\n",
			getstr(f->upvalues[i].name), f->upvalues[i].instack,
			f->upvalues[i].idx);
	}

	printf("\n");
	printf("sizecode: %d\n", f->sizecode);
	for (i = 0; i < f->sizecode; i++)
		decode_instruction(f, f->code[i]);

	printf("sizep: %d\n", f->sizep);
	for (i = 0; i < f->sizep; i++)
		dump_function(level + 1, f->p[i]);

}
Beispiel #13
0
void *polly_getDevicePtr(PollyGPUDevicePtr *Allocation) {
  dump_function();

  return (void *)Allocation->Cuda;
}
Beispiel #14
0
void polly_freeDeviceMemory(PollyGPUDevicePtr *Allocation) {
  dump_function();
  CuMemFreeFcnPtr((CUdeviceptr)Allocation->Cuda);
  free(Allocation);
}
Beispiel #15
0
PollyGPUFunction *polly_getKernel(const char *PTXBuffer,
                                  const char *KernelName) {
  dump_function();

  PollyGPUFunction *Function = malloc(sizeof(PollyGPUFunction));

  if (Function == 0) {
    fprintf(stdout, "Allocate memory for Polly GPU function failed.\n");
    exit(-1);
  }

  CUresult Res;
  CUlinkState LState;
  CUjit_option Options[6];
  void *OptionVals[6];
  float Walltime = 0;
  unsigned long LogSize = 8192;
  char ErrorLog[8192], InfoLog[8192];
  void *CuOut;
  size_t OutSize;

  // Setup linker options
  // Return walltime from JIT compilation
  Options[0] = CU_JIT_WALL_TIME;
  OptionVals[0] = (void *)&Walltime;
  // Pass a buffer for info messages
  Options[1] = CU_JIT_INFO_LOG_BUFFER;
  OptionVals[1] = (void *)InfoLog;
  // Pass the size of the info buffer
  Options[2] = CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES;
  OptionVals[2] = (void *)LogSize;
  // Pass a buffer for error message
  Options[3] = CU_JIT_ERROR_LOG_BUFFER;
  OptionVals[3] = (void *)ErrorLog;
  // Pass the size of the error buffer
  Options[4] = CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES;
  OptionVals[4] = (void *)LogSize;
  // Make the linker verbose
  Options[5] = CU_JIT_LOG_VERBOSE;
  OptionVals[5] = (void *)1;

  memset(ErrorLog, 0, sizeof(ErrorLog));

  CuLinkCreateFcnPtr(6, Options, OptionVals, &LState);
  Res = CuLinkAddDataFcnPtr(LState, CU_JIT_INPUT_PTX, (void *)PTXBuffer,
                            strlen(PTXBuffer) + 1, 0, 0, 0, 0);
  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "PTX Linker Error:\n%s\n%s", ErrorLog, InfoLog);
    exit(-1);
  }

  Res = CuLinkCompleteFcnPtr(LState, &CuOut, &OutSize);
  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "Complete ptx linker step failed.\n");
    fprintf(stdout, "\n%s\n", ErrorLog);
    exit(-1);
  }

  debug_print("CUDA Link Completed in %fms. Linker Output:\n%s\n", Walltime,
              InfoLog);

  Res = CuModuleLoadDataFcnPtr(&(Function->CudaModule), CuOut);
  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "Loading ptx assembly text failed.\n");
    exit(-1);
  }

  Res = CuModuleGetFunctionFcnPtr(&(Function->Cuda), Function->CudaModule,
                                  KernelName);
  if (Res != CUDA_SUCCESS) {
    fprintf(stdout, "Loading kernel function failed.\n");
    exit(-1);
  }

  CuLinkDestroyFcnPtr(LState);

  return Function;
}
Beispiel #16
0
int main(int argc, char *argv[])
{
	int ret = 0, len, ofs;
	unsigned int i, scan_size = 0, cnt = 0;
	unsigned long buf_size;
	void *map = NULL;
	a4l_desc_t dsc = { .sbdata = NULL };

	int (*dump_function) (a4l_desc_t *, a4l_cmd_t*, unsigned char *, int) =
		dump_text;

	/* Compute arguments */
	while ((ret = getopt_long(argc,
				  argv,
				  "vrd:s:S:c:mwk:h", 
				  cmd_read_opts, NULL)) >= 0) {
		switch (ret) {
		case 'v':
			verbose = 1;
			break;
		case 'r':
			real_time = 1;
			break;
		case 'd':
			filename = optarg;
			break;
		case 's':
			cmd.idx_subd = strtoul(optarg, NULL, 0);
			break;
		case 'S':
			cmd.stop_arg = strtoul(optarg, NULL, 0);
			break;
		case 'c':
			str_chans = optarg;
			break;
		case 'm':
			use_mmap = 1;
			break;
		case 'w':
			dump_function = dump_raw;
			break;
		case 'k':
			wake_count = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		default:
			do_print_usage();
			return 0;
		}
	}

	if (isatty(STDOUT_FILENO) && dump_function == dump_raw) {
		fprintf(stderr,
			"cmd_read: cannot dump raw data on a terminal\n\n");
		return -EINVAL;
	}

	/* Recover the channels to compute */
	do {
		cmd.nb_chan++;
		len = strlen(str_chans);
		ofs = strcspn(str_chans, ",");
		if (sscanf(str_chans, "%u", &chans[cmd.nb_chan - 1]) == 0) {
			fprintf(stderr, "cmd_read: bad channel argument\n");
			return -EINVAL;
		}
		str_chans += ofs + 1;
	} while (len != ofs);

	/* Update the command structure */
	cmd.scan_end_arg = cmd.nb_chan;
	cmd.stop_src = cmd.stop_arg != 0 ? TRIG_COUNT : TRIG_NONE;

	if (real_time != 0) {

		if (verbose != 0)
			printf("cmd_read: switching to real-time mode\n");

		/* Prevent any memory-swapping for this program */
		ret = mlockall(MCL_CURRENT | MCL_FUTURE);
		if (ret < 0) {
			ret = errno;
			fprintf(stderr, "cmd_read: mlockall failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		/* Turn the current process into an RT task */
		ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: rt_task_shadow failed (ret=%d)\n",
				ret);
			goto out_main;
		}
	}

	/* Open the device */
	ret = a4l_open(&dsc, filename);
	if (ret < 0) {
		fprintf(stderr, "cmd_read: a4l_open %s failed (ret=%d)\n",
			filename, ret);
		return ret;
	}

	if (verbose != 0) {
		printf("cmd_read: device %s opened (fd=%d)\n",
		       filename, dsc.fd);
		printf("cmd_read: basic descriptor retrieved\n");
		printf("\t subdevices count = %d\n", dsc.nb_subd);
		printf("\t read subdevice index = %d\n", dsc.idx_read_subd);
		printf("\t write subdevice index = %d\n", dsc.idx_write_subd);
	}

	/* Allocate a buffer so as to get more info (subd, chan, rng) */
	dsc.sbdata = malloc(dsc.sbsize);
	if (dsc.sbdata == NULL) {
		fprintf(stderr, "cmd_read: malloc failed \n");
		return -ENOMEM;
	}

	/* Get this data */
	ret = a4l_fill_desc(&dsc);
	if (ret < 0) {
		fprintf(stderr,
			"cmd_read: a4l_fill_desc failed (ret=%d)\n", ret);
		goto out_main;
	}

	if (verbose != 0)
		printf("cmd_read: complex descriptor retrieved\n");

	/* Get the size of a single acquisition */
	for (i = 0; i < cmd.nb_chan; i++) {
		a4l_chinfo_t *info;

		ret = a4l_get_chinfo(&dsc,
				     cmd.idx_subd, cmd.chan_descs[i], &info);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_get_chinfo failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0) {
			printf("cmd_read: channel %x\n", cmd.chan_descs[i]);
			printf("\t ranges count = %d\n", info->nb_rng);
			printf("\t bit width = %d (bits)\n", info->nb_bits);
		}

		scan_size += a4l_sizeof_chan(info);
	}

	if (verbose != 0) {
		printf("cmd_read: scan size = %u\n", scan_size);
		if (cmd.stop_arg != 0)
			printf("cmd_read: size to read = %u\n",
			       scan_size * cmd.stop_arg);
	}

	/* Cancel any former command which might be in progress */
	a4l_snd_cancel(&dsc, cmd.idx_subd);

	if (use_mmap != 0) {

		/* Get the buffer size to map */
		ret = a4l_get_bufsize(&dsc, cmd.idx_subd, &buf_size);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_get_bufsize() failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0)
			printf("cmd_read: buffer size = %lu bytes\n", buf_size);

		/* Map the analog input subdevice buffer */
		ret = a4l_mmap(&dsc, cmd.idx_subd, buf_size, &map);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_mmap() failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0)
			printf
				("cmd_read: mmap performed successfully (map=0x%p)\n",
				 map);
	}

	ret = a4l_set_wakesize(&dsc, wake_count);
	if (ret < 0) {
		fprintf(stderr,
			"cmd_read: a4l_set_wakesize failed (ret=%d)\n", ret);
		goto out_main;
	}

	if (verbose != 0)
		printf("cmd_read: wake size successfully set (%lu)\n", 
		       wake_count);

	/* Send the command to the input device */
	ret = a4l_snd_command(&dsc, &cmd);
	if (ret < 0) {
		fprintf(stderr,
			"cmd_read: a4l_snd_command failed (ret=%d)\n", ret);
		goto out_main;
	}

	if (verbose != 0)
		printf("cmd_read: command successfully sent\n");

	if (use_mmap == 0) {

		/* Fetch data */
		do {
			/* Perform the read operation */
			ret = a4l_async_read(&dsc, buf, BUF_SIZE, A4L_INFINITE);
			if (ret < 0) {
				fprintf(stderr,
					"cmd_read: a4l_read failed (ret=%d)\n",
					ret);
				goto out_main;
			}

			/* Display the results */
			if (dump_function(&dsc, &cmd, buf, ret) < 0) {
				ret = -EIO;
				goto out_main;
			}

			/* Update the counter */
			cnt += ret;

		} while (ret > 0);

	} else {
		unsigned long front = 0;

		/* Fetch data without any memcpy */
		do {

			/* Retrieve and update the buffer's state
			   (In input case, we recover how many bytes are available
			   to read) */
			ret = a4l_mark_bufrw(&dsc, cmd.idx_subd, front, &front);
			if (ret == -ENOENT)
				break;
			else if (ret < 0) {
				fprintf(stderr,
					"cmd_read: a4l_mark_bufrw() failed (ret=%d)\n",
					ret);
				goto out_main;
			}

			/* If there is nothing to read, wait for an event
			   (Note that a4l_poll() also retrieves the data amount
			   to read; in our case it is useless as we have to update
			   the data read counter) */
			if (front == 0) {
				ret = a4l_poll(&dsc, cmd.idx_subd, A4L_INFINITE);
				if (ret == 0)
					break;
				else if (ret < 0) {
					fprintf(stderr,
						"cmd_read: a4l_poll() failed (ret=%d)\n",
						ret);
					goto out_main;
				}
			}

			/* Display the results */
			if (dump_function(&dsc,
					  &cmd,
					  &((unsigned char *)map)[cnt % buf_size],
					  front) < 0) {
				ret = -EIO;
				goto out_main;
			}

			/* Update the counter */
			cnt += front;

		} while (1);
	}

	if (verbose != 0)
		printf("cmd_read: %d bytes successfully received\n", cnt);

	ret = 0;

out_main:

	if (use_mmap != 0)
		/* Clean the pages table */
		munmap(map, buf_size);

	/* Free the buffer used as device descriptor */
	if (dsc.sbdata != NULL)
		free(dsc.sbdata);

	/* Release the file descriptor */
	a4l_close(&dsc);

	return ret;
}
Beispiel #17
0
int main(int argc, char *argv[])
{
	int err = 0;
	unsigned int cnt = 0;
	a4l_desc_t dsc = { .sbdata = NULL };
	a4l_sbinfo_t *sbinfo;
	a4l_chinfo_t *chinfo;
	a4l_rnginfo_t *rnginfo;

	int (*dump_function) (a4l_desc_t *, unsigned char *, int) = dump_text;

	/* Compute arguments */
	while ((err = getopt_long(argc,
				  argv,
				  "vrd:s:S:c:R:y:wh", insn_read_opts,
				  NULL)) >= 0) {
		switch (err) {
		case 'v':
			verbose = 1;
			break;
		case 'd':
			filename = optarg;
			break;
		case 's':
			idx_subd = strtoul(optarg, NULL, 0);
			break;
		case 'S':
			scan_size = strtoul(optarg, NULL, 0);
			break;
		case 'c':
			idx_chan = strtoul(optarg, NULL, 0);
			break;
		case 'R':
			idx_rng = strtoul(optarg, NULL, 0);
			dump_function = dump_converted;
			break;
		case 'w':
			dump_function = dump_raw;
			break;
		case 'y':
			dump_function = dump_calibrated;
			calibration_file = optarg;
			break;
		case 'h':
		default:
			do_print_usage();
			return 0;
		}
	}

	if (isatty(STDOUT_FILENO) && dump_function == dump_raw) {
		fprintf(stderr,
			"insn_read: cannot dump raw data on a terminal\n\n");
		return -EINVAL;
	}

	/* Open the device */
	err = a4l_open(&dsc, filename);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: a4l_open %s failed (err=%d)\n",
			filename, err);
		return err;
	}

	if (verbose != 0) {
		printf("insn_read: device %s opened (fd=%d)\n", filename,
		       dsc.fd);
		printf("insn_read: basic descriptor retrieved\n");
		printf("\t subdevices count = %d\n", dsc.nb_subd);
		printf("\t read subdevice index = %d\n", dsc.idx_read_subd);
		printf("\t write subdevice index = %d\n", dsc.idx_write_subd);
	}

	/* Allocate a buffer so as to get more info (subd, chan, rng) */
	dsc.sbdata = malloc(dsc.sbsize);
	if (dsc.sbdata == NULL) {
		err = -ENOMEM;
		fprintf(stderr, "insn_read: info buffer allocation failed\n");
		goto out_insn_read;
	}

	/* Get this data */
	err = a4l_fill_desc(&dsc);
	if (err < 0) {
		fprintf(stderr, "insn_read: a4l_fill_desc failed (err=%d)\n",
			err);
		goto out_insn_read;
	}

	if (verbose != 0)
		printf("insn_read: complex descriptor retrieved\n");

	/* If no subdevice index was set, look for an analog input
	   subdevice */
	if (idx_subd == -1)
		idx_subd = dsc.idx_read_subd;

	if (idx_subd == -1) {
		fprintf(stderr,
			"insn_read: no analog input subdevice available\n");
		err = -EINVAL;
		goto  out_insn_read;
	}

	if (verbose != 0)
		printf("insn_read: selected subdevice index = %d\n", idx_subd);

	/* We must check that the subdevice is really an AI one
	   (in case, the subdevice index was set with the option -s) */
	err = a4l_get_subdinfo(&dsc, idx_subd, &sbinfo);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: get_sbinfo(%d) failed (err = %d)\n",
			idx_subd, err);
		err = -EINVAL;
		goto out_insn_read;
	}

	if ((sbinfo->flags & A4L_SUBD_TYPES) != A4L_SUBD_AI) {
		fprintf(stderr,
			"insn_read: wrong subdevice selected "
			"(not an analog input)\n");
		err = -EINVAL;
		goto out_insn_read;
	}

	if (idx_rng >= 0) {

		err = a4l_get_rnginfo(&dsc,
				      idx_subd, idx_chan, idx_rng, &rnginfo);
		if (err < 0) {
			fprintf(stderr,
				"insn_read: failed to recover range descriptor\n");
			goto out_insn_read;
		}

		if (verbose != 0) {
			printf("insn_read: range descriptor retrieved\n");
			printf("\t min = %ld\n", rnginfo->min);
			printf("\t max = %ld\n", rnginfo->max);
		}
	}

	/* Retrieve the subdevice data size */
	err = a4l_get_chinfo(&dsc, idx_subd, idx_chan, &chinfo);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: info for channel %d on subdevice %d not available (err=%d)\n",
			idx_chan, idx_subd, err);
		goto out_insn_read;
	}

	/* Set the data size to read */
	scan_size *= a4l_sizeof_chan(chinfo);

	if (verbose != 0) {
		printf("insn_read: channel width is %u bits\n",
		       chinfo->nb_bits);
		printf("insn_read: global scan size is %u\n", scan_size);
	}

	while (cnt < scan_size) {
		int tmp = (scan_size - cnt) < BUF_SIZE ?
			(scan_size - cnt) : BUF_SIZE;

		/* Perform the synchronous read */
		err = a4l_sync_read(&dsc,
				    idx_subd, CHAN(idx_chan), 0, buf, tmp);

		if (err < 0) {
			fprintf(stderr,
				"insn_read: a4l_sync_read failed (err=%d)\n",
				err);
			goto out_insn_read;
		}

		/* Dump the read data */
		tmp = dump_function(&dsc, buf, err);
		if (tmp < 0) {
			err = tmp;
			goto out_insn_read;
		}

		/* Update the count */
		cnt += err;
	}

	if (verbose != 0)
		printf("insn_read: %u bytes successfully received\n", cnt);

	err = 0;

out_insn_read:

	/* Free the information buffer */
	if (dsc.sbdata != NULL)
		free(dsc.sbdata);

	/* Release the file descriptor */
	a4l_close(&dsc);

	return err;
}