#include "../l502api_private.h" #include "../lpcie_ioctls.h" #include #include #include #include #include #include #include #include #include #define LPCIE_CLASS_DIR "/sys/class/lpcie" static int32_t f_ioctl(int fd, unsigned long int req, void* val) { return ioctl(fd, req, val) ? X502_ERR_IOCTL_FAILD : X502_ERR_OK; } int32_t l502_port_fpga_reg_write(t_x502_hnd hnd, uint32_t reg, uint32_t val) { t_lpcie_mem_rw mem_wr = {reg,val}; return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_MEMFPGA_WR, &mem_wr); } int32_t l502_port_fpga_reg_read(t_x502_hnd hnd, uint32_t reg, uint32_t *val) { t_lpcie_mem_rw mem_wr = {reg,0}; int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_MEMFPGA_RD, &mem_wr); if ((err == X502_ERR_OK) && (val != NULL)) *val = mem_wr.val; return err; } int32_t l502_port_stream_set_params(t_x502_hnd hnd, t_lpcie_stream_ch_params *par) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_SET_PARAMS, par); } int32_t l502_port_stream_start(t_x502_hnd hnd, uint32_t ch, uint32_t single) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), single ? LPCIE_IOCTL_STREAM_START_SINGLE : LPCIE_IOCTL_STREAM_START, &ch); } int32_t l502_port_stream_stop(t_x502_hnd hnd, uint32_t ch, uint32_t flags) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_STOP, &ch); } int32_t l502_port_stream_free(t_x502_hnd hnd, uint32_t ch, uint32_t flags) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_FREE, &ch); } int32_t l502_port_stream_rdy_size(t_x502_hnd hnd, uint32_t ch, uint32_t *rdy_size) { t_lpcie_get_rdy_par rdy_par = {ch,0}; int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_GET_RDY_SIZE, &rdy_par); if ((err == X502_ERR_OK) && (rdy_size != NULL)) *rdy_size = rdy_par.rdy_size; return err; } int32_t l502_port_cycle_load_start(t_x502_hnd hnd, uint32_t ch, uint32_t size, uint32_t min_irq_step) { t_lpcie_cycle_set_par par; memset(&par, 0, sizeof(par)); par.ch = ch; par.size = size; par.irq_step = min_irq_step; return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_LOAD, &par); } int32_t l502_port_cycle_setup(t_x502_hnd hnd, uint32_t ch, uint32_t evt) { t_lpcie_cycle_evt_par par; memset(&par, 0, sizeof(par)); par.ch = ch; par.evt = evt; return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_SWITCH, &par); } int32_t l502_port_cycle_stop(t_x502_hnd hnd, uint32_t ch, uint32_t evt) { t_lpcie_cycle_evt_par par; memset(&par, 0, sizeof(par)); par.ch = ch; par.evt = evt; return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_STOP, &par); } int32_t l502_port_cycle_check_setup(t_x502_hnd hnd, uint32_t ch, uint32_t *done) { t_lpcie_cycle_check_setup_par par; int32_t err; memset(&par, 0, sizeof(par)); par.ch = ch; err = f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_CHECK_SETUP, &par); if (err == X502_ERR_OK) *done = par.done; return err; } int32_t l502_port_renew_info(t_x502_hnd hnd) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_RELOAD_DEVINFO, NULL); } int32_t l502_port_get_drv_ver(t_x502_hnd hnd, uint32_t *ver) { return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_GET_DRV_VERSION, ver); } int32_t l502_port_stream_read(t_x502_hnd hnd, uint32_t *buff, uint32_t size, uint32_t timeout) { struct timeval tmval = {timeout/1000, (timeout%1000)*1000}; uint32_t rcv_size = 0; int out = 0; int32_t err = X502_ERR_OK; while (!out && (err == X502_ERR_OK) && (rcv_size < size)) { fd_set rd_set; int sel = 0; FD_ZERO(&rd_set); FD_SET(L502_PCI_IFACE_FILE(hnd), &rd_set); sel = select(L502_PCI_IFACE_FILE(hnd)+1, &rd_set, NULL, NULL, &tmval); if ((sel > 0) && (FD_ISSET(L502_PCI_IFACE_FILE(hnd), &rd_set))) { ssize_t rd = read(L502_PCI_IFACE_FILE(hnd), &buff[rcv_size], (size-rcv_size)*4); if (rd>0) { rcv_size += rd/4; } else if (rd == 0) { out = 1; } else { err = X502_ERR_RECV; } } else if (sel==0) { out = 1; } else { err = X502_ERR_RECV; } } return err != X502_ERR_OK ? err : (int32_t)rcv_size; } int32_t l502_port_stream_write(t_x502_hnd hnd, const uint32_t *buff, uint32_t size, uint32_t timeout) { struct timeval tmval = {timeout/1000, (timeout%1000)*1000}; uint32_t snd_size = 0; int32_t err = X502_ERR_OK; int out = 0; while (!out && (err == X502_ERR_OK) && (snd_size < size)) { fd_set wr_set; int sel = 0; FD_ZERO(&wr_set); FD_SET(L502_PCI_IFACE_FILE(hnd), &wr_set); sel = select(L502_PCI_IFACE_FILE(hnd)+1, NULL, &wr_set, NULL, &tmval); if ((sel > 0) && (FD_ISSET(L502_PCI_IFACE_FILE(hnd), &wr_set))) { ssize_t wr = write(L502_PCI_IFACE_FILE(hnd), &buff[snd_size], (size-snd_size)*4); if (wr > 0) { snd_size += wr/4; } else if (wr==0) { out = 1; } else { err = X502_ERR_SEND; } } else if (sel==0) { out = 1; } else { err = X502_ERR_SEND; } } return err != X502_ERR_OK ? err : (int32_t)snd_size; } static int32_t f_get_file_par(const char *path, char *filebuf, const char *file, char *res, uint32_t req_size, uint32_t *read_size) { int f; int32_t err = X502_ERR_OK; strcpy(filebuf, path); strcat(filebuf, file); f = open (filebuf, O_RDONLY); if (f == -1) { err = X502_ERR_GET_INFO; } else { ssize_t rd = read(f, res, req_size); if (rd < 0) { err = X502_ERR_GET_INFO; } else { if (read_size!=NULL) *read_size = rd; } close(f); } return err; } static void f_del_eol(char *str) { for ( ; *str; str++) { if ((*str=='\n') || (*str=='\r')) *str = '\0'; } } static int32_t f_fill_devlist(const char *devname, t_x502_devrec *info) { int32_t err = 0; int path_len = strlen(devname) + strlen(LPCIE_CLASS_DIR) + 2; char *filename = malloc(path_len + 21); char *path = malloc(path_len); if ((filename != NULL) && (path != NULL)) { sprintf(path, LPCIE_CLASS_DIR "/%s", devname); err = f_get_file_par(path, filename, "/name", info->devname, sizeof(info->devname), NULL); if (err == X502_ERR_OK) f_del_eol(info->devname); if (err == X502_ERR_OK) { /* получаем серийный номер устройства */ err = f_get_file_par(path, filename, "/sn", info->serial, sizeof(info->serial), NULL); if (err == X502_ERR_OK) f_del_eol(info->serial); } /* получаем информацию, открыто ли устройство */ if (err == X502_ERR_OK) { char val = '0'; err = f_get_file_par(path, filename, "/opened", &val, 1, NULL); if ((err == X502_ERR_OK) && (val!='0')) info->flags |= X502_DEVFLAGS_DEVREC_OPENED; } /* получаем информацию, присутствует ли BlackFin */ if (err == X502_ERR_OK) { char val = '0'; if ((f_get_file_par(path, filename, "/bf", &val, 1, NULL) == X502_ERR_OK) && (val != '0')) { info->flags |= X502_DEVFLAGS_BF_PRESENT; } if ((f_get_file_par(path, filename, "/dac", &val, 1, NULL) == X502_ERR_OK) && (val != '0')) { info->flags |= X502_DEVFLAGS_DAC_PRESENT; } if ((f_get_file_par(path, filename, "/gal", &val, 1, NULL) == X502_ERR_OK) && (val != '0')) { info->flags |= X502_DEVFLAGS_GAL_PRESENT; } } if (err == X502_ERR_OK) { char *devname_cpy = malloc(strlen(devname)+1); if (devname_cpy!=NULL) { strcpy(devname_cpy, devname); err = l502_devlist_gen(info, devname_cpy); if (err != X502_ERR_OK) { free(devname_cpy); } } else { err = X502_ERR_MEMORY_ALLOC; } } } else { err = X502_ERR_MEMORY_ALLOC; } free(filename); free(path); return err; } int32_t l502_port_free_iface_data(void *intptr) { free(intptr); return X502_ERR_OK; } int32_t l502_port_open(t_x502_hnd hnd, const t_x502_devrec *devinfo) { const char *devname = (const char *)devinfo->internal->iface_data; int32_t err = X502_ERR_OK; int path_len = strlen(devname)+6; char *path = malloc(path_len); if (path != NULL) { int file; snprintf(path, path_len, "/dev/%s", devname); file = open(path, O_RDWR); if (file != -1) { hnd->iface_data = malloc(sizeof(t_pci_iface_data)); if (hnd->iface_data == NULL) { err = X502_ERR_MEMORY_ALLOC; close(file); } else { L502_PCI_IFACE_FILE(hnd) = file; } } else { /** @todo Разобрать коды ошибок */ err = X502_ERR_DEVICE_OPEN; } free(path); } else { err = X502_ERR_MEMORY_ALLOC; } return err; } int32_t l502_port_close(t_x502_hnd hnd) { if (hnd->iface_data !=NULL) { close(L502_PCI_IFACE_FILE(hnd)); free(hnd->iface_data); hnd->iface_data = NULL; } return X502_ERR_OK; } X502_EXPORT(int32_t) L502_GetDevRecordsList(t_x502_devrec *list, uint32_t size, uint32_t flags, uint32_t *devcnt) { uint32_t curcnt = 0; int32_t err = X502_ERR_OK; /* все устройства, поддерживаемые драйвером LPCIE, создают папку в директории класса устройств lpcie*/ DIR *class_dir = opendir(LPCIE_CLASS_DIR); if (class_dir!=NULL) { struct dirent *dev_ent; /* читаем все записи в директории класса */ while ((dev_ent=readdir(class_dir))!=NULL) { /* проверяем, что имя начинается с lpcie */ if (!memcmp(dev_ent->d_name, "lpcie", sizeof("lpcie")-1)) { t_x502_devrec info; int info_used = 0; X502_DevRecordInit(&info); /* получаем информацию о устройстве из служебных файлов, * предоставляемых драйвером */ if (f_fill_devlist(dev_ent->d_name, &info) == X502_ERR_OK) { /* если нужны только не открытые, то уже открытое * устройство пропускаем */ if (!(flags & X502_GETDEVS_FLAGS_ONLY_NOT_OPENED) || !(info.flags & X502_DEVFLAGS_DEVREC_OPENED)) { /* если есть место в списке - то сохраняем * полученную информацию */ if ((list!=NULL) && (curcnt < size)) { list[curcnt] = info; info_used = 1; } curcnt++; } } if (!info_used) X502_FreeDevRecordList(&info,1); } } closedir(class_dir); } if (devcnt != NULL) *devcnt = curcnt; return err != X502_ERR_OK ? err : curcnt > size ? (int32_t)size : (int32_t)curcnt ; }