В качестве теста первого уровня моего драйвера PCI я надеялся, что смогу получить доступ к области pci_iomap через /sys/bus/pci/devices/0000:01:00.0/ resource0 файл из моего пользовательского приложения. Страница man для mmap, образец программы, который я нашел, и другие сообщения, похоже, указывают на то, что пользовательский процесс доступа должен работать. Но некоторые статьи, похоже, указывают на то, что вызов mmap должен выполняться изнутри ядра через ioctl-аксессор.linux mmap доступ к области памяти PCI из пользовательского пространства
Вопрос: Должен ли mmap() файла ресурса PCI sysfs работать из прикладного пространства?
Когда я запускаю свой код, mmap возвращает то, что выглядит как действительный адрес, но при попытке доступа к виртуальному адресу появляется ошибка шины. Я считаю, что мое конечное устройство PCI-Xilinx AXI-моста, находящееся на FPGA, работает нормально, так как я могу R/W к нему через Windows PCIe utilty (Win Driver) Я нахожусь на процессоре NXP LS1021A ARM7 с Linux версии 3.12 0,37.
Благодаря Билл
Не то, что я хочу, чтобы кто-нибудь отлаживать код, но то, что я делаю лучше всего можно объяснить кодом, так что я включил его также. Приносим извинения, если вставленный код не отображается правильно. Надеюсь, это так.
я запускаю ниже код и получить корень @ ls1021aiot: ~ # pcimem /sys/bus/pci/devices/0000:01:00.0/resource0 0 ш
/SYS/автобус/PCI/устройства/0000: 01: 00.0/resource0 открыт. Смещение цели 0x0, размер страницы 4096 Карта маска 0xFFF mmap (0, 4096, 0x3, 0x1, 3, 0x0) mmap (0, 4096, 0x3, 0x1, 3, 0x0) Память PCI 4096 байт region to map_base 0x76fb5000. Доступ к карте памяти PCI 0x 76FB5000. Ошибка шины
/*
* pcimem.c: Simple program to read/write from/to a pci device from userspace.
*
* Copyright (C) 2010, Bill Farrow ([email protected])
*
* Based on the devmem2.c code
* Copyright (C) 2000, Jan-Derk Bakker ([email protected])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <linux/pci.h>
#define PRINT_ERROR \
do { \
fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); \
} while(0)
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
int main(int argc, char **argv) {
int fd;
void *map_base, *virt_addr;
uint32_t read_result, writeval;
char *filename;
off_t target;
int access_type = 'w';
if(argc < 3) {
// pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0 0x100 w 0x00
// argv[0] [1] [2] [3] [4]
fprintf(stderr, "\nUsage:\t%s { sys file } { offset } [ type [ data ] ]\n"
"\tsys file: sysfs file for the pci resource to act on\n"
"\toffset : offset into pci memory region to act upon\n"
"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"
"\tdata : data to be written\n\n",
argv[0]);
exit(1);
}
filename = argv[1];
target = strtoul(argv[2], 0, 0);
if(argc > 3)
access_type = tolower(argv[3][0]);
if((fd = open(filename, O_RDWR | O_SYNC)) == -1){
PRINT_ERROR;
}
printf("%s opened.\n", filename);
printf("Target offset is 0x%x, page size is %ld map mask is 0x%lX\n", (int) target, sysconf(_SC_PAGE_SIZE), MAP_MASK);
fflush(stdout);
/* Map one page */
#if 0
//map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) (target & ~MAP_MASK));
//map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
#endif
printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (target & ~MAP_MASK));
if(map_base == (void *) -1){
printf("PCI Memory mapped ERROR.\n");
PRINT_ERROR;
close(fd);
return 1;
}
printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));
printf("PCI Memory mapped %ld byte region to map_base 0x%08lx.\n", MAP_SIZE, (unsigned long) map_base);
fflush(stdout);
virt_addr = map_base + (target & MAP_MASK);
printf("PCI Memory mapped access 0x %08X.\n", (uint32_t) virt_addr);
switch(access_type) {
case 'b':
read_result = *((uint8_t *) virt_addr);
break;
case 'h':
read_result = *((uint16_t *) virt_addr);
break;
case 'w':
read_result = *((uint32_t *) virt_addr);
printf("READ Value at offset 0x%X (%p): 0x%X\n", (int) target, virt_addr, read_result);
break;
default:
fprintf(stderr, "Illegal data type '%c'.\n", access_type);
exit(2);
}
fflush(stdout);
if(argc > 4) {
writeval = strtoul(argv[4], 0, 0);
switch(access_type) {
case 'b':
*((uint8_t *) virt_addr) = writeval;
read_result = *((uint8_t *) virt_addr);
break;
case 'h':
*((uint16_t *) virt_addr) = writeval;
read_result = *((uint16_t *) virt_addr);
break;
case 'w':
*((uint32_t *) virt_addr) = writeval;
read_result = *((uint32_t *) virt_addr);
break;
}
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
fflush(stdout);
}
if(munmap(map_base, MAP_SIZE) == -1) { PRINT_ERROR;}
close(fd);
return 0;
}
Я скомпилировал оба моих драйвера и приложение pci_debug для x86_64 (linux 3.16.7), и они работали правильно. Это оставляет мне поверить, что мне не хватает чего-то необходимого для 32-битного процессора (40-битная внутренняя адресация). Устройство PCI отображается в базу адресов 0x40_0000_0000. cat/proc/cpuinfo показывает функцию lpae. –
Я забыл упомянуть приложение pci_debug, выполненное для ошибок шины процессора ARM, таких как мое тестовое приложение. Mmap возвращает void *, к которому я добавляю смещение, это разрешено в LPAE? Я продолжаю копать. Thanks –