pio: add pio print < PIO to turn a PIO dump into human readable
This commit is contained in:
parent
3affc3bd5f
commit
0d2d96c484
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
fexc
|
||||
bin2fex
|
||||
fex2bin
|
||||
bootinfo
|
||||
fel
|
||||
pio
|
||||
*.o
|
||||
*.swp
|
||||
|
||||
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ CC = gcc
|
||||
CFLAGS = -g -O0 -Wall -Wextra
|
||||
CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L
|
||||
|
||||
TOOLS = fexc bin2fex fex2bin bootinfo fel
|
||||
TOOLS = fexc bin2fex fex2bin bootinfo fel pio
|
||||
|
||||
MISC_TOOLS = phoenix_info
|
||||
|
||||
|
||||
150
pio.c
Normal file
150
pio.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* needs _BSD_SOURCE for htole and letoh */
|
||||
#define _BSD_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#define PIO_REG_SIZE 0x228 /*0x300*/
|
||||
#define PIO_PORT_SIZE 0x24
|
||||
|
||||
#define errf(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
static inline int _read(int fd, char *buf, size_t l)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
while (l > 0) {
|
||||
rc = read(fd, buf, l);
|
||||
if (rc >= 0)
|
||||
break;
|
||||
else if (rc < 0 && errno != EINTR) {
|
||||
errf("read: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int read_fixed_stdin(char *buf, size_t wanted)
|
||||
{
|
||||
ssize_t rc;
|
||||
char eof;
|
||||
|
||||
while (wanted > 0) {
|
||||
rc = _read(0, buf, wanted);
|
||||
if (rc > 0) {
|
||||
wanted -= rc;
|
||||
buf += rc;
|
||||
} else if (rc == 0) {
|
||||
errf("read: input too small\n");
|
||||
goto fail;
|
||||
} else if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (_read(0, &eof, 1) == 0)
|
||||
return 1;
|
||||
|
||||
errf("read: input too large\n");
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pio_status {
|
||||
int mul_sel;
|
||||
int pull;
|
||||
int drv_level;
|
||||
int data;
|
||||
};
|
||||
|
||||
#define PIO_REG_CFG(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x00)
|
||||
#define PIO_REG_DLEVEL(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x14)
|
||||
#define PIO_REG_PULL(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x1C)
|
||||
#define PIO_REG_DATA(B, N) ((B) + (N)*0x24 + 0x10)
|
||||
|
||||
#define LE32TOH(X) le32toh(*((uint32_t*)(X)))
|
||||
|
||||
static int pio_get(const char *buf, uint32_t port, uint32_t port_num, struct pio_status *pio)
|
||||
{
|
||||
uint32_t val;
|
||||
uint32_t port_num_func, port_num_pull;
|
||||
uint32_t offset_func, offset_pull;
|
||||
|
||||
port_num_func = port_num >> 3;
|
||||
offset_func = ((port_num - (port_num_func << 3)) << 2);
|
||||
|
||||
port_num_pull = port_num >> 4;
|
||||
offset_pull = ((port_num - (port_num_pull << 4)) << 1);
|
||||
|
||||
/* func */
|
||||
val = LE32TOH(PIO_REG_CFG(buf, port, port_num_func));
|
||||
pio->mul_sel = (val>>offset_func) & 0x07;
|
||||
|
||||
/* pull */
|
||||
val = LE32TOH(PIO_REG_PULL(buf, port, port_num_pull));
|
||||
pio->pull = (val>>offset_pull) & 0x03;
|
||||
|
||||
/* dlevel */
|
||||
val = LE32TOH(PIO_REG_DLEVEL(buf, port, port_num_pull));
|
||||
pio->drv_level = (val>>offset_pull) & 0x03;
|
||||
|
||||
/* i/o data */
|
||||
if (pio->mul_sel > 1)
|
||||
pio->data = -1;
|
||||
else {
|
||||
val = LE32TOH(PIO_REG_CFG(buf, port, port_num_func));
|
||||
pio->data = (val >> port_num) & 0x01;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print(const char *buf)
|
||||
{
|
||||
int port, i;
|
||||
struct pio_status pio;
|
||||
for (port=0; port < 10 /*PIO_REG_SIZE/0x24*/; port++) {
|
||||
for (i=0; i<28; i++) {
|
||||
if (pio_get(buf, port, i, &pio)) {
|
||||
printf("P%c%d", 'A'+port, i+1);
|
||||
printf("<%x>", pio.mul_sel);
|
||||
printf("<%x>", pio.pull);
|
||||
printf("<%x>", pio.drv_level);
|
||||
if (pio.data >= 0)
|
||||
printf("<%x>", pio.data);
|
||||
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static int read_and_print(void)
|
||||
{
|
||||
char buf[PIO_REG_SIZE];
|
||||
|
||||
if (read_fixed_stdin(buf, PIO_REG_SIZE)) {
|
||||
print(buf);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int usage(const char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage: %s print < PIO\n", argv0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 2 && (strncmp("print", argv[1], 5) == 0))
|
||||
return read_and_print();
|
||||
else
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user