From 13054fd168f489c7310018e470dee3c5273a2a8d Mon Sep 17 00:00:00 2001 From: Thomas Cort Date: Sun, 10 Nov 2013 12:06:27 -0500 Subject: [PATCH] eepromread: support for reading from /dev/eeprom eepromread could only read EEPROMs through the /dev/i2c interface. Once the cat24c256 driver is started and claims/reserves the device, it can no longer be read through the /dev/i2c interface. This patch adds support for reading from EEPROMs through the /dev/eeprom interface. For example, to read the on-board eeprom on the BBB, one would do `eepromread -f /dev/eepromb1s50 -i`. Change-Id: If08ce37231e593982eeb109bdd6d5458ad271108 --- commands/eepromread/board_info.c | 36 ++++++++++++++--------- commands/eepromread/eepromread.1 | 8 ++++-- commands/eepromread/eepromread.c | 49 +++++++++++++++++++++----------- commands/eepromread/eepromread.h | 9 ++++-- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/commands/eepromread/board_info.c b/commands/eepromread/board_info.c index 6521b4a64..4f02c53ec 100644 --- a/commands/eepromread/board_info.c +++ b/commands/eepromread/board_info.c @@ -16,9 +16,12 @@ * Attempt to read the board info from an eeprom on this board. */ -static int board_info_beaglebone(int fd, i2c_addr_t address, int flags); -static int board_info_cape_a0(int fd, i2c_addr_t address, int flags); -static int board_info_cape_a1(int fd, i2c_addr_t address, int flags); +static int board_info_beaglebone(int fd, i2c_addr_t address, int flags, + enum device_types device_type); +static int board_info_cape_a0(int fd, i2c_addr_t address, int flags, + enum device_types device_type); +static int board_info_cape_a1(int fd, i2c_addr_t address, int flags, + enum device_types device_type); /* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */ typedef struct beaglebone_info @@ -68,7 +71,8 @@ typedef struct cape_info_a1 } cape_info_a1_t; static int -board_info_beaglebone(int fd, i2c_addr_t address, int flags) +board_info_beaglebone(int fd, i2c_addr_t address, int flags, + enum device_types device_type) { int r; int i, j; @@ -76,7 +80,7 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags) beaglebone_info_t boneinfo; r = eeprom_read(fd, address, 0x0000, &boneinfo, - sizeof(beaglebone_info_t), flags); + sizeof(beaglebone_info_t), flags, device_type); if (r == -1) { fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r); return -1; @@ -102,7 +106,8 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags) } static int -board_info_cape_a0(int fd, i2c_addr_t address, int flags) +board_info_cape_a0(int fd, i2c_addr_t address, int flags, + enum device_types device_type) { int r; int i, j; @@ -110,7 +115,7 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags) cape_info_a0_t capeinfo; r = eeprom_read(fd, address, 0x0000, &capeinfo, - sizeof(cape_info_a0_t), flags); + sizeof(cape_info_a0_t), flags, device_type); if (r == -1) { fprintf(stderr, "failed to read cape A0 info r=%d\n", r); return -1; @@ -148,7 +153,8 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags) } static int -board_info_cape_a1(int fd, i2c_addr_t address, int flags) +board_info_cape_a1(int fd, i2c_addr_t address, int flags, + enum device_types device_type) { int r; int i, j; @@ -156,7 +162,7 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags) cape_info_a1_t capeinfo; r = eeprom_read(fd, address, 0x0000, &capeinfo, - sizeof(cape_info_a1_t), flags); + sizeof(cape_info_a1_t), flags, device_type); if (r == -1) { fprintf(stderr, "failed to read cape A0 info r=%d\n", r); return -1; @@ -194,12 +200,14 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags) } int -board_info(int fd, i2c_addr_t address, int flags) +board_info(int fd, i2c_addr_t address, int flags, + enum device_types device_type) { int r; uint8_t magic_number[6]; - r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags); + r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags, + device_type); if (r == -1) { printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN"); return 0; @@ -211,11 +219,11 @@ board_info(int fd, i2c_addr_t address, int flags) /* Check if Cape Rev A0, Cape Rev A1, or on-board EEPROM */ if (magic_number[4] == 'A' && magic_number[5] == '0') { - board_info_cape_a0(fd, address, flags); + board_info_cape_a0(fd, address, flags, device_type); } else if (magic_number[4] == 'A' && magic_number[5] == '1') { - board_info_cape_a1(fd, address, flags); + board_info_cape_a1(fd, address, flags, device_type); } else { - board_info_beaglebone(fd, address, flags); + board_info_beaglebone(fd, address, flags, device_type); } } else { printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN"); diff --git a/commands/eepromread/eepromread.1 b/commands/eepromread/eepromread.1 index 53115ac99..7462aa431 100644 --- a/commands/eepromread/eepromread.1 +++ b/commands/eepromread/eepromread.1 @@ -43,6 +43,10 @@ number is sent with the memory address. Use this when reading EDID. .TP 20 .B eepromread -f /dev/i2c-3 -n # read the EDID info from the display on I2C bus 3 on the BeagleBoard-xM. +.TP 20 +.B eepromread -f /dev/eepromb1s50 -i +# access the EEPROM through the /dev/eeprom interface once the +cat24c256 driver has been started. .SH DESCRIPTION .PP \fIeepromread\fR is a simple tool for viewing the contents of an EEPROM. @@ -51,5 +55,5 @@ detect, \fIeepromread\fR can properly format each of the fields and display the information via the \fI-i\fR command line option. .SH NOTES If the \fIcat24c256\fR driver has claimed the EEPROM device that this -program is attempting to read from, then this program will fail. Once -a driver claims an I2C device, the driver has exclusive access. +program is attempting to read from, then you must access it through +the /dev/eeprom interface rather than the /dev/i2c interface. diff --git a/commands/eepromread/eepromread.c b/commands/eepromread/eepromread.c index 4ecee6bdc..3c1f807da 100644 --- a/commands/eepromread/eepromread.c +++ b/commands/eepromread/eepromread.c @@ -15,8 +15,9 @@ #include "eepromread.h" static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, - void *buf, size_t buflen, int flags); -static int eeprom_dump(int fd, i2c_addr_t addr, int flags); + void *buf, size_t buflen, int flags, enum device_types device_type); +static int eeprom_dump(int fd, i2c_addr_t addr, int flags, + enum device_types device_type); #define DEFAULT_I2C_DEVICE "/dev/i2c-1" #define DEFAULT_I2C_ADDRESS 0x50 @@ -26,16 +27,11 @@ static int eeprom_dump(int fd, i2c_addr_t addr, int flags); * larger, so to read the whole EEPROM, the task is broken down into 128 byte * chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do * the read. - * - * A future enhancement might be to add support for the /dev/eeprom interface - * and if one way fails, fall back to the other. /dev/eeprom can fail if the - * eeprom driver isn't running and /dev/i2c can fail if the eeprom driver - * claimed the eeprom device. */ static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, - size_t buflen, int flags) + size_t buflen, int flags, enum device_types device_type) { int r; minix_i2c_ioctl_exec_t ioctl_exec; @@ -46,6 +42,20 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, return -1; } + /* if /dev/eeprom, then use read() */ + if (device_type == EEPROM_DEVICE) { + + off_t offset; + + offset = lseek(fd, memaddr, SEEK_SET); + if (offset != memaddr) { + return -1; + } + + return read(fd, buf, buflen); + + } + /* else /dev/i2c, use i2c_ioctl_exec_t interface */ memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; @@ -77,7 +87,7 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, - size_t buflen, int flags) + size_t buflen, int flags, enum device_types device_type) { int r; uint16_t i; @@ -87,11 +97,11 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, return -1; } - for (i = 0; i < buflen; i += 128) { r = __eeprom_read128(fd, addr, memaddr + i, buf + i, - ((buflen - i) < 128) ? (buflen - i) : 128, flags); + ((buflen - i) < 128) ? (buflen - i) : 128, flags, + device_type); if (r == -1) { return -1; } @@ -104,14 +114,14 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, * Read 256 bytes and print it to the screen in HEX and ASCII. */ static int -eeprom_dump(int fd, i2c_addr_t addr, int flags) +eeprom_dump(int fd, i2c_addr_t addr, int flags, enum device_types device_type) { int i, j, r; uint8_t buf[256]; memset(buf, '\0', 256); - r = eeprom_read(fd, addr, 0x0000, buf, 256, flags); + r = eeprom_read(fd, addr, 0x0000, buf, 256, flags, device_type); if (r == -1) { return r; } @@ -163,6 +173,7 @@ main(int argc, char *argv[]) int ch, iflag = 0, read_flags = 0; char *device = DEFAULT_I2C_DEVICE; i2c_addr_t address = DEFAULT_I2C_ADDRESS; + enum device_types device_type = DEFAULT_DEVICE; setprogname(*argv); @@ -185,6 +196,10 @@ main(int argc, char *argv[]) } } + /* determine whether to use /dev/i2c or /dev/eeprom interface */ + device_type = + strstr(device, "i2c") == NULL ? EEPROM_DEVICE : I2C_DEVICE; + fd = open(device, O_RDWR); if (fd == -1) { fprintf(stderr, "open(): %s\n", strerror(errno)); @@ -192,15 +207,16 @@ main(int argc, char *argv[]) } if (iflag == 1) { - r = board_info(fd, address, read_flags); + r = board_info(fd, address, read_flags, device_type); if (r == -1) { fprintf(stderr, "board_info(): %s\n", strerror(errno)); return 1; } } else { - r = eeprom_dump(fd, address, read_flags); + r = eeprom_dump(fd, address, read_flags, device_type); if (r == -1) { - fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno)); + fprintf(stderr, "eeprom_dump(): %s\n", + strerror(errno)); return 1; } } @@ -213,4 +229,3 @@ main(int argc, char *argv[]) return 0; } - diff --git a/commands/eepromread/eepromread.h b/commands/eepromread/eepromread.h index 733ba2cf3..60dadc3fe 100644 --- a/commands/eepromread/eepromread.h +++ b/commands/eepromread/eepromread.h @@ -1,8 +1,13 @@ #ifndef __EEPROMREAD_H #define __EEPROMREAD_H +enum device_types { I2C_DEVICE, EEPROM_DEVICE }; +#define DEFAULT_DEVICE I2C_DEVICE + int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, - size_t buflen, int flags); -int board_info(int fd, i2c_addr_t address, int flags); + size_t buflen, int flags, enum device_types device_type); + +int board_info(int fd, i2c_addr_t address, int flags, + enum device_types device_type); #endif /* __EEPROMREAD_H */