utils/hw
utils
/
hw
1
1
Fork 0

Тестовые утилиты для ЗОСРВ "Нейтрино" редакции 2020

This commit is contained in:
commit 558b729c13
160 changed files with 2987 additions and 0 deletions

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
LIST=ALL
include recurse.mk

42
README.md Normal file
View File

@ -0,0 +1,42 @@
## Дерево исходных кодов
```
|- utils/
| |- btime/ - Вывести время с момента включения питания
| |- i2c-scan/ - Сканер шины I2C и чтение/запись произвольного регистра I2C устройства
| |- int-attach/ - Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении
| |- pci-attach/ - Подключиться к PCI устройству
| |- rr/ - Чтение/запись произвольного адреса
| |- sertest/ - Тест последовательных портов (COM-портов) с передачей, получением и проверкой пакетов с данными
| |- spitest/ - Получение/установка конфигурации SPI и тестовый обмен с устройствами на шине
| |- ticksize/ - Установка периода срабатывания системного таймера и тест задержки прерывания системного таймера
| `- Makefile - Правила сборки дерева исходников
|
`- Makefile - Правила сборки дерева исходников
```
## Сборка утилит
- Установить и настроить [комплект разработчика](https://help.kpda.ru/help/topic/ru.kpda.doc.dev_tools_ru/html/devkit/devkit.html) для [ЗОСРВ "Нейтрино" редакции 2020](https://help.kpda.ru/help/index.jsp).
- Выполнить команду:
```
make
```
## Запуск утилит
Примеры представлены в описаниях утилит в каталогах с их исходным кодом:
- `btime` - [ссылка на описание утилиты](utils/btime/)
- `i2c-scan` - [ссылка на описание утилиты](utils/i2c-scan/)
- `int-attach` - [ссылка на описание утилиты](utils/int-attach/)
- `pci-attach` - [ссылка на описание утилиты](utils/pci-attach/)
- `rr` - [ссылка на описание утилиты](utils/rr/)
- `sertest` - [ссылка на описание утилиты](utils/sertest/)
- `spitest` - [ссылка на описание утилиты](utils/spitest/)
- `ticksize` - [ссылка на описание утилиты](utils/ticksize/)

2
utils/Makefile Normal file
View File

@ -0,0 +1,2 @@
LIST=utils
include recurse.mk

2
utils/btime/Makefile Normal file
View File

@ -0,0 +1,2 @@
LIST=OS
include recurse.mk

26
utils/btime/README.md Normal file
View File

@ -0,0 +1,26 @@
### btime
Вывести время с момента включения питания.
### Синтаксис
```btime [-s "строка"]```
### Опции
- **-s строка**
опциональная текстовая строка с комментарием
### Описание
Утилита выводит время, прошедшее с момента включения питания системы. Значение времени рассчитывается на основе счётчика тактов процессора (см. ClockCycles()).
Может использоваться для замера времени загрузки системы, например, в загрузочном образе ОС.
Можно вызвать несколько раз для вывода значения времени на разных этапах загрузки: запуск ядра ОС, запуск драйверов, прикладного ПО и т.п.
### Предостережения
Учтите, что учитывается всё время прошедшее с момента включения питания процессора, включая начальную инициализацию системы, работу загрузчиков, BIOS и т.п.
### Примеры
```btime -s "Kernel Boot Time: ```

10
utils/btime/btime.use Normal file
View File

@ -0,0 +1,10 @@
%C Time passed from board start
Syntax:
%C [options]
Options:
-s descr Description string
Example:
btime -s "Kernel Boot Time: "

15
utils/btime/common.mk Normal file
View File

@ -0,0 +1,15 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
INSTALLDIR=sbin
define PINFO
PINFO DESCRIPTION=btime
endef
USEFILE=$(PROJECT_ROOT)/btime.use
include $(MKFILES_ROOT)/qtargets.mk

42
utils/btime/main.c Normal file
View File

@ -0,0 +1,42 @@
/*
* Get current cycles counter value by ClockCycles() kernel call.
* Print time passed from board start
*
* (c) 2019, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <inttypes.h>
int main (int argc, char *argv[])
{
int c;
char *dstr = NULL;
uint64_t btime;
uint64_t cycles;
uint64_t cps;
while ( ( c = getopt( argc, argv, "s:" ) ) != -1 )
{
switch ( c )
{
case 's': // be verbose
dstr = optarg;
break;
}
}
cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec / 1000;
cycles = ClockCycles();
btime = cycles / cps;
printf( "%s %lldms\n", (dstr) ? dstr : "", btime );
return ( 0 );
}

2
utils/btime/nto/Makefile Normal file
View File

@ -0,0 +1,2 @@
LIST=CPU
include recurse.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

2
utils/i2c-scan/Makefile Normal file
View File

@ -0,0 +1,2 @@
LIST=OS
include recurse.mk

92
utils/i2c-scan/README.md Normal file
View File

@ -0,0 +1,92 @@
### i2c-scan
Сканер шины I2C и чтение/запись произвольного регистра I2C устройства.
### Синтаксис
```i2c-scan [-d устройство] [-f] [-a адрес] [-r смещение] [-w значение] [-c количество]]```
### Опции
- **-d устройство**
Устройство I2C. Например: /dev/i2c1. По умолчанию: /dev/i2c0
- **-f**
Сканировать шину. Задано по умолчанию.
- **-a адрес**
Адрес I2C устройства на шине, например, 0x60.
- **-r смещение**
Смещение регистра I2C устройства. По умолчанию: 0.
- **-w значение**
Значение для записи в регистр устройства.
- **-c количество**
Количество регистров для чтения/записи. По умолчанию: 1.
### Описание
Утилита i2c-scan сканирует шину I2C, последовательно перебирая доступные адреса (0-127), и выводит таблицу с присутствующими на шине устройствами.
При задании адреса устройства на шине (опция -a) считывает указанное количество регистров (опция -c) со смещением, заданным опцией -r.
Пример работы сканера для шин I2C0 и I2C1:
```
# i2c-scan                
Scanning I2C device /dev/i2c0 for I2C devices...
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 6f  
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
Scanning done  
#  
# i2c-scan -d /dev/i2c1   
Scanning I2C device /dev/i2c1 for I2C devices...
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
10: -- -- -- -- -- -- -- -- 18 19 -- -- -- -- -- --  
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
Scanning done
```
### Предостережения
I2C устройства, требующие первичной инициализации/включения и/или специфичных многобайтовых транзакций, могут не отображаться сканером шины или не выполнять запросы чтения/записи регистров.
### Примеры
Сканировать шину I2C0:
```i2c-scan```
Сканировать шину I2C1:
```i2c-scan -d /dev/i2c1```
Считать регистр со смещением 0x50 устройства с адресом 0x60 на шине I2C0
```i2c-scan -a 0x60 -r 0x50```

13
utils/i2c-scan/common.mk Normal file
View File

@ -0,0 +1,13 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
USEFILE=$(PROJECT_ROOT)/$(NAME).use
INSTALLDIR=sbin
define PINFO
PINFO DESCRIPTION=I2C scan utility
endef
include $(MKFILES_ROOT)/qtargets.mk

View File

@ -0,0 +1,22 @@
%C - I2C scan utility
Options:
-d Device. Default: /dev/i2c0
-f Scan I2C bus for devices
-a I2C device address
-r Register offset
-w Value to write to the device
-c Number of registers to read/write
Examples:
Scan I2C 0 bus
%C
Scan I2C 1 bus
%C -d /dev/i2c1
Read register 0x50 from I2C device with address 0x60
%C -a 0x60 -r 0x50
Write value 0x2 to register 0x50 from I2C device 0x60
%C -a 0x60 -r 0x50

236
utils/i2c-scan/main.c Normal file
View File

@ -0,0 +1,236 @@
/*
* I2C scan utility
*
* (c) 2015, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <hw/i2c.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#define REGISTER_SIZE_BYTES 1
#define UTILITY_MODE_RW 0
#define UTILITY_MODE_FIND 1
/* Devctl type SEND pointers: */
uint8_t *devctl_send_message; /* Pointer to devctl message */
uint8_t *register_send_dev_num; /* Pointer to register number in devctl message */
uint8_t *data_send; /* Pointer to data to send in devctl message */
i2c_send_t *send_header; /* Pointer to header */
/* Devctl type SEND-RECEIVE pointers: */
uint8_t *devctl_message; /* Pointer to devctl message */
i2c_sendrecv_t *send_receive_header; /* Pointer to header */
uint8_t *register_dev_num; /* Pointer to register number in devctl message */
uint8_t *data; /* Pointer to data to send in devctl message */
/* Desciption: Initialization global structures */
void i2c_init()
{
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
send_receive_header = (void *)devctl_message;
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
data = (uint8_t *)register_dev_num;
devctl_send_message = calloc( 1, sizeof( i2c_send_t ) + REGISTER_SIZE_BYTES + sizeof( uint16_t ) );
register_send_dev_num = ((uint8_t *)devctl_send_message + sizeof( i2c_send_t ));
data_send = (uint8_t *)((uint8_t *)register_send_dev_num + sizeof( *register_send_dev_num ));
send_header = (void *)devctl_send_message;
}
/*
* Desciption: Read value from I2C device
* Parameters: device_desc - opened file descriptior
* reg_num - register number into device
* addr - addr device in I2C bus
* Return:
* -1 - if error detected
* register value - if Ok
*/
int read_i2c_register( int device_desc, int reg_num, uint8_t addr )
{
int ret;
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
send_receive_header = (void *)devctl_message;
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
data = (uint8_t *)register_dev_num;
*register_dev_num = reg_num;
send_receive_header->slave.addr = addr;
send_receive_header->slave.fmt = I2C_ADDRFMT_7BIT;
send_receive_header->send_len = 1;
send_receive_header->stop = 1;
send_receive_header->recv_len = REGISTER_SIZE_BYTES;
ret = devctl( device_desc, DCMD_I2C_SENDRECV, devctl_message, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES, NULL );
if ( ret )
return (-1);
else
return *data;
}
/*
* Desciption: Write value to I2C device
* Parameters: device_desc - opened file descriptior
* reg_num - register number into device
* addr - addr device in I2C bus
* value - value to write
* Return:
* EXIT_FAILURE - error detected,
* 0 - if OK
*/
int write_i2c_register( int device_desc, int reg_num, uint8_t addr, uint16_t value )
{
int ret;
*register_send_dev_num = reg_num;
*((uint8_t *)data_send) = value;
send_header->slave.addr = addr;
send_header->slave.fmt = I2C_ADDRFMT_7BIT;
send_header->len = sizeof( *register_send_dev_num ) + sizeof( *data_send );
send_header->stop = 1;
delay( 10 );
ret = devctl( device_desc, DCMD_I2C_SEND, devctl_send_message, sizeof( i2c_send_t ) + send_header->len, NULL );
delay( 10 );
if ( ret )
{
fprintf( stderr, "Error writing to register %d device %d value 0x%X.(%s)\n", reg_num, addr, value, strerror( ret ) );
return (EXIT_FAILURE);
} else
return (0);
}
void scan_i2c( int fd )
{
int i, j;
fprintf( stderr, " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n" );
for ( j = 0; j < 128; j += 16 )
{
fprintf( stderr, "%02x: ", j );
for ( i = 0; i < 16 ; i++ )
{
if ( read_i2c_register( fd, 0, i + j ) >= 0 )
fprintf( stderr, "%02x ", i + j );
else
fprintf( stderr, "-- " );
}
fprintf( stderr, "\n" );
}
}
int main( int argc, char **argv )
{
char *device_name = "/dev/i2c0";
int option,
device_desc = -1,
i,
write_value = -1,
utility_mode = UTILITY_MODE_FIND,
reg_num = 0,
addr = 0,
val,
register_count = 1;
while ( (option = getopt( argc, argv, "d:a:r:c:w:f" )) != -1 )
{
switch ( option )
{
case 'd':
device_name = optarg;
break;
case 'a':
addr = strtol( optarg, NULL, 0 );
utility_mode = UTILITY_MODE_RW;
break;
case 'r':
reg_num = strtol( optarg, NULL, 0 );
utility_mode = UTILITY_MODE_RW;
break;
case 'c':
register_count = strtol( optarg, NULL, 0 );
break;
case 'w':
write_value = strtol( optarg, NULL, 0 );
utility_mode = UTILITY_MODE_RW;
break;
case 'f':
utility_mode = UTILITY_MODE_FIND;
break;
default:
return (-1);
}
}
device_desc = open( device_name, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO );
if ( device_desc < 0 )
{
perror( "Failed to open I2C device " );
return (-1);
}
i2c_init();
if ( utility_mode == UTILITY_MODE_FIND )
{
printf( "Scanning I2C device %s for I2C devices...\n", device_name );
scan_i2c( device_desc );
printf( "Scanning done \n" );
close( device_desc );
return (0);
}
printf( "I2C device 0x%X \n", addr );
for ( i = 0; i < register_count; i++ )
{
if ( write_value != -1 )
{
val = write_i2c_register( device_desc, reg_num + i, addr, write_value );
if ( !val )
printf( "Writing value 0x%X to register 0x%X\n", write_value, (reg_num + i) );
else {
fprintf( stderr, "Error writing device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
close( device_desc );
return (-1);
}
}
val = read_i2c_register( device_desc, reg_num + i, addr );
if ( val < 0 )
{
fprintf( stderr, "Error reading from device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
close( device_desc );
return (-1);
} else
printf( "Reg[0x%02X] = 0x%X\n", reg_num + i, val );
}
close( device_desc );
return (0);
}

View File

@ -0,0 +1,2 @@
LIST=CPU
include recurse.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=OS
include recurse.mk

View File

@ -0,0 +1,28 @@
### int-attach
Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении
### Синтаксис
```int-attach -i N```
### Опции
- **-i номер_прерывания**
навесить обработчик на указанный номер
### Описание
Утилита int-attach навешивает минимальный обработчик на заданный номер прерывания и выводит отладочное сообщение при возникновении этого прерывания.
Подключаемый обработчик прерывания содержит минимальный код, увеличивающий счётчик количества перехваченных прерываний и маскирующий прерывание. Размаскирование прерывания выполняется в основном потоке функции main() после вывода отладочного сообщения в консоль.
Может использоваться для отладки и проверки того, что указанное прерывание возникает в ожидаемый момент времени, например, при обращении к аппаратуре, отправка сообщения в COM порт, работа с диском и т.п.
Одновременно можно запустить несколько копий программы с различными номерами прерываний.
### Предостережения
Учтите, что вывод отладочного сообщения достаточно длительная операция и на это время прерывание будет оставаться замаскированным, что значительно увеличит задержку его обработки в основном драйвере/программ и может нарушить их работу.
### Примеры
Навесить обработчик на прерывание 10
```int-attach -i 10 &```

View File

@ -0,0 +1,13 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
USEFILE=$(PROJECT_ROOT)/$(NAME).use
INSTALLDIR=sbin
define PINFO
PINFO DESCRIPTION=Interrupt attach
endef
include $(MKFILES_ROOT)/qtargets.mk

View File

@ -0,0 +1,81 @@
/*
* Interrupt attach
*
* (c) 2005, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include <sys/neutrino.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
struct sigevent int_event;
int id = -1;
unsigned long int_n = 1;
volatile unsigned long int_conter = 0;
const struct sigevent *handler( void *area, int id )
{
InterruptMask( int_n, id );
int_conter++;
return (&int_event);
}
int main( int argc, char **argv )
{
int opt;
// Allow IO operations
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) != EOK )
{
printf( "You must be root!" );
return (-1);
}
printf( "Interrupt attach program \n" );
while ( (opt = getopt ( argc, argv, "i:" )) != -1 )
{
switch ( opt )
{
case 'i':
int_n = strtoul( optarg, NULL, 0 );
break;
}
}
if( int_n < 0 )
return (-1);
else
printf( "Attaching handler for interrupt %lu ( 0x%lX ) \n\n", int_n, int_n );
int_event.sigev_notify = SIGEV_INTR;
// register an interrupt handler
id = InterruptAttach( int_n, &handler, NULL, 0, 0 );
if ( id == -1 )
{
perror( " Cannot attach interrupt handler " );
return (-1);
}
while ( 1 )
{
InterruptWait( 0, NULL );
printf( "Got interrupt %lu ( 0x%lX ) #%4ld\n", int_n, int_n, int_conter );
InterruptUnmask( int_n, id );
}
InterruptDetach( id );
return (0);
}

View File

@ -0,0 +1,5 @@
%C - interrupt attach
Options:
i <num> - Attach interrupt handler for interrupt <num> (InterruptAttach() is used).
Interrupt is masked in interrupt handler and then unmasked in main thread.

View File

@ -0,0 +1,2 @@
LIST=CPU
include recurse.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,8 @@
LIST=OS
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -0,0 +1,54 @@
### pci-attach
Подключиться к PCI устройству.
### Синтаксис
```pci-attach [-s] [-v Vendor -d ID] [-arD] [-S]]```
### Опции
- **-s**
Выполнить сканирование шины PCI и вывести список устройств.
- **-v PCI_Vendor**
- **-d PCI_ID**
Подключиться к PCI устройству с указанными идентификаторами Vendor и ID.
- **-a**
Не отключаться от устройства. По умолчанию: отключиться от устройства после вывода назначенных ресурсов.
- **-r**
Смапировать, считать и вывести значения из назначенных PCI устройству диапазонов памяти.
- **-D**
Считать и вывести значения из конфигурационной области PCI устройства.
- **-S**
Вывести значения из логической базы данных ресурсов PCI сервера (см. rsrcdbmgr_*())
### Описание
Утилита *pci-attach* подключается к PCI устройству с помощью функции pci_attach() и выводит назначенные PCI устройству ресурсы: диапазоны памяти и IO, прерывание.
В отличие от утилиты *pci*, сканирующей шину PCI и выводящей информацию из конфигурационного пространства PCI, но не подключающейся к устройству, *pci-attach* подключается к устройству с заданием флагов инициализации PCI_INIT_ALL и при этом PCI сервер назначает ресурсы устройству, если это требуется.
### Предостережения
Если к PCI устройству уже выполнено подключение из драйвера или какой-либо другой программы, то повторное подключение может привести к нарушению их работы.
### Примеры
Подключиться к PCI устройству с идентификаторами 0x8086:0x1533 и вывести назначенные устройству PCI ресурсы:
```pci-attach -v 0x8086 -d 0x1533```
Сканировать шину PCI:
```pci-attach -s```

View File

@ -0,0 +1,9 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
USEFILE=$(PROJECT_ROOT)/$(NAME).use
INSTALLDIR=sbin
include $(MKFILES_ROOT)/qtargets.mk

View File

@ -0,0 +1,8 @@
LIST=CPU
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -0,0 +1 @@
include ../../../common.mk

View File

@ -0,0 +1,315 @@
/*
* PCI attach
*
* (c) 2013, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <hw/pci.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/rsrcdbmgr.h>
#include <sys/rsrcdbmsg.h>
int attach_to_device( unsigned vendor, unsigned device, int read_mem, int read_config, int stay_attached, int scan )
{
void *hdl;
struct pci_dev_info pci_info;
unsigned *pci_mem;
uintptr_t pci_io;
uint32_t pci_config[256];
int i,
j;
memset( &pci_info, 0, sizeof( pci_info ) );
if ( scan )
{
pci_info.BusNumber = vendor;
pci_info.DevFunc = device;
hdl = pci_attach_device( NULL, PCI_SEARCH_BUSDEV | PCI_SHARE, 0, &pci_info );
} else {
pci_info.VendorId = vendor;
pci_info.DeviceId = device;
hdl = pci_attach_device( NULL, PCI_SEARCH_VENDEV | PCI_SHARE, 0, &pci_info );
}
if ( hdl == NULL )
{
if ( scan == 0 )
perror( "Device not found:" );
return (-1);
}
printf( "PCI device: %4x:%4x Bus %4d Devfunc %#4x Class %#8x\n",
pci_info.VendorId, pci_info.DeviceId, pci_info.BusNumber, pci_info.DevFunc, pci_info.Class );
if ( read_config )
{
pci_read_config32( pci_info.BusNumber, pci_info.DevFunc, 0, 256, &pci_config );
printf( "Dumping PCI configuration before pci_attach_device:\n" );
for ( i = 1; i <= (256 / 4); i++ )
{
printf( "[0x%2X] 0x%08X ", (i - 1) * 4, pci_config[i - 1] );
if ( i % 5 == 0 )
printf( "\n" );
}
printf( "\n\n" );
}
if ( scan )
return (0);
else
hdl = pci_attach_device( hdl, PCI_INIT_ALL | PCI_INIT_ROM | PCI_SHARE |
PCI_MASTER_ENABLE | PCI_USE_MSI, 0, &pci_info );
if ( hdl == NULL )
{
perror( "PCI attach failed:" );
return (-1);
}
if ( read_config )
{
pci_read_config32( pci_info.BusNumber, pci_info.DevFunc, 0, 256, &pci_config );
printf( "Dumping PCI configuration after pci_attach_device:\n" );
for ( i = 1; i <= (256 / 4); i++ )
{
printf( "[0x%2X] 0x%08X ", (i - 1) * 4, pci_config[i - 1] );
if ( i % 5 == 0 )
printf( "\n" );
}
printf( "\n\n" );
}
if ( pci_info.Irq != 0xff )
printf ("Interrupt %#x (%d)\n", pci_info.Irq, pci_info.Irq );
for ( i = 0; i < 6; i++ )
{
if ( pci_info.BaseAddressSize[i] )
{
if ( PCI_IS_IO( pci_info.CpuBaseAddress[i] ) )
{
printf( "[%d] IO space at %#llx for %#x bytes\n", i,
PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ), pci_info.BaseAddressSize[i] );
if ( read_mem )
{
pci_io = mmap_device_io( 4, PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ) );
if ( pci_io == MAP_DEVICE_FAILED )
{
printf( "mmap_device_io for physical address %#llx failed\n",
PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ) );
continue;
}
munmap_device_io( pci_io, 4 );
}
} else
if ( PCI_IS_MEM( pci_info.CpuBaseAddress[i] ) )
{
printf( "[%d] Memory space at %#llx for %#x bytes\n", i,
PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ), pci_info.BaseAddressSize[i] );
if ( read_mem )
{
pci_mem = mmap_device_memory( NULL, pci_info.BaseAddressSize[i],
PROT_READ | PROT_WRITE | PROT_NOCACHE,
0, PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ) );
if ( pci_mem == MAP_FAILED )
{
printf( "mmap_device_memory for physical address %#llx failed\n",
PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ) );
continue;
}
printf( "Reading from device PCI memory \n" );
for ( j = 1; j <= 32; j++ )
{
printf( "[0x%2X] 0x%08X ", (j - 1) * 4, *(pci_mem + (j - 1)) );
if ( j % 5 == 0 )
printf( "\n" );
}
printf( "\n\n" );
munmap_device_memory( pci_mem, pci_info.BaseAddressSize[i] );
}
}
}
}
if ( pci_info.PciRom != 0x0 )
{
printf( "PCI ROM 0x%llx \n", PCI_ROM_ADDR( pci_info.PciRom ) );
if ( read_mem )
{
pci_mem = mmap_device_memory( NULL, pci_info.RomSize,
PROT_READ | PROT_WRITE | PROT_NOCACHE,
0, PCI_ROM_ADDR( pci_info.PciRom ) );
if ( pci_mem == MAP_FAILED )
{
printf( "mmap_device_memory for physical address %#llx failed\n",
PCI_ROM_ADDR( pci_info.PciRom ) );
pci_detach_device( hdl );
return (-1);
}
printf( "Reading from device PCI ROM memory : 0x%X \n", *pci_mem );
munmap_device_memory( pci_mem, pci_info.RomSize );
}
}
if ( stay_attached == 0 )
pci_detach_device( hdl );
else
while ( 1 )
sleep(1);
return 0;
}
void dump_rsrcdbmgr( char *name, int type )
{
rsrc_alloc_t rsrc[256];
int i,
cnt;
cnt = rsrcdbmgr_query( rsrc, sizeof( rsrc ) / sizeof( rsrc[0] ), 0, type );
printf( "%s - (%d items):\n", name, cnt );
if ( !cnt )
return;
printf( "%-4s %-10s %-10s %s", "Idx", "Start", "End", "Flags\n" );
for ( i = 0; i < cnt && i < sizeof( rsrc ) / sizeof( rsrc[0] ); i++ )
printf( "%3d: %010llx %010llx 0x%x\n",
i, rsrc[i].start, rsrc[i].end, rsrc[i].flags );
if ( cnt > sizeof( rsrc ) / sizeof( rsrc[0] ) )
printf( "...\n" );
}
void dump_rsrcdbmgr_db()
{
printf( "\nSystem resource manager database\n" );
dump_rsrcdbmgr( "Memory", RSRCDBMGR_MEMORY );
dump_rsrcdbmgr( "IRQs", RSRCDBMGR_IRQ );
dump_rsrcdbmgr( "PCI Mem", RSRCDBMGR_PCI_MEMORY );
dump_rsrcdbmgr( "IO Ports", RSRCDBMGR_IO_PORT );
printf( "\n-------------------------------------------------\n\n" );
printf( "Used resources\n" );
dump_rsrcdbmgr( "Memory", RSRCDBMGR_MEMORY|RSRCDBMGR_FLAG_USED );
dump_rsrcdbmgr( "IRQs", RSRCDBMGR_IRQ|RSRCDBMGR_FLAG_USED );
dump_rsrcdbmgr( "PCI Mem", RSRCDBMGR_PCI_MEMORY|RSRCDBMGR_FLAG_USED );
dump_rsrcdbmgr( "IO Ports", RSRCDBMGR_IO_PORT|RSRCDBMGR_FLAG_USED );
printf( "\n" );
}
int main( int argc, char *argv[] )
{
unsigned vendor = 0,
device = 0;
int read_mem = 0,
read_config = 0,
scan_flag = 0,
stay_attached = 0,
system_res = 0,
opt,
i,
j,
pd;
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) == -1 )
{
printf( "You must be root!" );
return (-1);
}
while ( (opt = getopt( argc, argv, "sv:d:arDS" )) != -1 )
{
switch ( opt )
{
case 's':
scan_flag = 1;
break;
case 'v':
vendor = strtoul( optarg, NULL, 0 );
break;
case 'd':
device = strtoul( optarg, NULL, 0 );
break;
case 'a':
stay_attached = 1;
break;
case 'r':
read_mem = 1;
break;
case 'D':
read_config = 1;
break;
case 'S':
system_res = 1;
break;
default:
printf( "Unsupported option.\n" );
return (-1);
}
}
if ( system_res )
{
dump_rsrcdbmgr_db();
return (0);
}
pd = pci_attach( 0 );
if ( pd == (-1) )
{
perror( "pci_attach" );
return (-1);
}
if ( scan_flag )
{
printf( "Scanning PCI bus\n" );
for ( i = 0; i < 256; i++ )
for ( j = 0; j < 256; j++ )
{