前言
在之前提到过的测试模式开启后,无须数字签名的axidma驱动就安装成功了,设备管理器中可以很开心的看到我们xilinx dma的设备,但是实际使用中,有时候并不会只用一台设备。当遇到了多台设备可以支持吗?以两台为例:
一.驱动层:
点开设备属性,事件查看驱动信息,发现PCI编号是不同的,也就是区分我们代码里devpath的依据,
比如新增一个设备,同样的设备信息会看到设备号为7024,(上图7025为我们后加的设备)7024和7025由逻辑端指定分配(可改),第一步要解决的就是官方驱动里是否支持我们自定义的设备编号,打开驱动目录进行查找,
能查到两个相关文件里对这个值进行了配置,先随便打开一个,不难看到刚好是没有7025的支持的,可以先把不用的设备号比如7028先更改为7025保存,
重新安装驱动,就能出现最开始的画面了,在驱动层面上就支持了两个不同的设备,增加设备可以用同样的方法。
二.应用层:
还是以官方的例程为例,下一篇会重点介绍官方例程怎么使用,这里只介绍一下设备的区分
打开xdma_rw.c,这是官方用于读写寄存器或者内存空间值的demo,不论是我们后面自己开发还是怎么使用,一般都会和demo一样,有获取上面设备号的函数
官方demo里是
static int get_devices(GUID guid, char* devpath, size_t len_devpath) static int get_devices(GUID guid, char* devpath, size_t len_devpath) { HDEVINFO device_info = SetupDiGetClassDevs((LPGUID)&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (device_info == INVALID_HANDLE_VALUE) { fprintf(stderr, "GetDevices INVALID_HANDLE_VALUE\n"); exit(-1); } SP_DEVICE_INTERFACE_DATA device_interface; device_interface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // enumerate through devices DWORD index; for (index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &guid, index, &device_interface); ++index) { // get required buffer size ULONG detailLength = 0; if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, NULL, 0, &detailLength, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { fprintf(stderr, "SetupDiGetDeviceInterfaceDetail - get length failed\n"); break; } // allocate space for device interface detail PSP_DEVICE_INTERFACE_DETAIL_DATA dev_detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, detailLength); if (!dev_detail) { fprintf(stderr, "HeapAlloc failed\n"); break; } dev_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // get device interface detail if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, dev_detail, detailLength, NULL, NULL)) { fprintf(stderr, "SetupDiGetDeviceInterfaceDetail - get detail failed\n"); HeapFree(GetProcessHeap(), 0, dev_detail); break; } StringCchCopy(devpath, len_devpath, dev_detail->DevicePath); HeapFree(GetProcessHeap(), 0, dev_detail); } SetupDiDestroyDeviceInfoList(device_info); return index; }
其中for (index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &guid, index, &device_interface); ++index)做到了遍历所有设备,但是会只返回最后一个设备,也就是说比如我们在7024和7025设备同时在线时,加载成功的是7025设备,那么我们就先只让他查找一次就好了比如改成这样,在应用开发的时候比如我们会分配cpu1核2核去专门做收发那么在另一个设备里最好换成3核4核做同样的工作
static int get_devices(GUID guid, char *devpath, size_t len_devpath) { size_t result = 0; HDEVINFO device_info = SetupDiGetClassDevs((LPGUID)&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (device_info == INVALID_HANDLE_VALUE) { LOGE(LOG_TAG"GetDevices INVALID_HANDLE_VALUE\n"); return -(int)GetLastError(); } SP_DEVICE_INTERFACE_DATA device_interface; device_interface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // enumerate through devices DWORD index; index = 1; SetupDiEnumDeviceInterfaces(device_info, NULL, &guid, index, &device_interface); // get required buffer size ULONG detailLength = 0; if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, NULL, 0, &detailLength, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { LOGE(LOG_TAG"SetupDiGetDeviceInterfaceDetail - get length failed\n"); //break; } // allocate space for device interface detail PSP_DEVICE_INTERFACE_DETAIL_DATA dev_detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, detailLength); if (!dev_detail) { LOGE(LOG_TAG"HeapAlloc failed\n"); //break; } dev_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // get device interface detail if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, dev_detail, detailLength, NULL, NULL)) { LOGE(LOG_TAG"SetupDiGetDeviceInterfaceDetail - get detail failed\n"); HeapFree(GetProcessHeap(), 0, dev_detail); //break; } StringCchCopy(devpath, len_devpath, dev_detail->DevicePath); HeapFree(GetProcessHeap(), 0, dev_detail); SetupDiDestroyDeviceInfoList(device_info); return index; }