diff --git a/ppi.c b/ppi.c index ce999049..a4faec97 100644 --- a/ppi.c +++ b/ppi.c @@ -43,24 +43,33 @@ extern char * progname; -/* - * set 'get' and 'set' appropriately for subsequent passage to ioctl() - * to get/set the specified PPI registers. - */ -static int ppi_getops(int reg, unsigned long * get, unsigned long * set) +enum { + PPI_READ, + PPI_WRITE, + PPI_SHADOWREAD +}; + +int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action) { + static unsigned char shadow[3]; + int shadow_num; + unsigned long set, get; + switch (reg) { case PPIDATA: - *set = PPISDATA; - *get = PPIGDATA; + set = PPISDATA; + get = PPIGDATA; + shadow_num = 0; break; case PPICTRL: - *set = PPISCTRL; - *get = PPIGCTRL; + set = PPISCTRL; + get = PPIGCTRL; + shadow_num = 1; break; case PPISTATUS: - *set = PPISSTATUS; - *get = PPIGSTATUS; + set = PPISSTATUS; + get = PPIGSTATUS; + shadow_num = 2; break; default: fprintf(stderr, "%s: avr_set(): invalid register=%d\n", @@ -69,27 +78,37 @@ static int ppi_getops(int reg, unsigned long * get, unsigned long * set) break; } + switch (action) { + case PPI_SHADOWREAD: + *v = shadow[shadow_num]; + break; + case PPI_READ: + ioctl(fd, get, v); + shadow[shadow_num]=*v; + break; + case PPI_WRITE: + shadow[shadow_num]=*v; + ioctl(fd, set, v); + break; + } return 0; } - /* * set the indicated bit of the specified register. */ int ppi_set(int fd, int reg, int bit) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD); + v |= bit; + rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE); + if (rc) return -1; - ioctl(fd, get, &v); - v |= bit; - ioctl(fd, set, &v); - return 0; } @@ -100,17 +119,15 @@ int ppi_set(int fd, int reg, int bit) int ppi_clr(int fd, int reg, int bit) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD); + v &= ~bit; + rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE); + if (rc) return -1; - ioctl(fd, get, &v); - v &= ~bit; - ioctl(fd, set, &v); - return 0; } @@ -121,16 +138,14 @@ int ppi_clr(int fd, int reg, int bit) int ppi_get(int fd, int reg, int bit) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + rc = ppi_shadow_access(fd, reg, &v, PPI_READ); + v &= bit; + if (rc) return -1; - ioctl(fd, get, &v); - v &= bit; - return v; /* v == bit */ } @@ -140,17 +155,15 @@ int ppi_get(int fd, int reg, int bit) int ppi_toggle(int fd, int reg, int bit) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD); + v ^= bit; + rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE); + if (rc) return -1; - ioctl(fd, get, &v); - v ^= bit; - ioctl(fd, set, &v); - return 0; } @@ -161,16 +174,14 @@ int ppi_toggle(int fd, int reg, int bit) int ppi_getall(int fd, int reg) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + rc = ppi_shadow_access(fd, reg, &v, PPI_READ); + if (rc) return -1; - ioctl(fd, get, &v); - - return (int)v; + return v; /* v == bit */ } /* @@ -179,16 +190,14 @@ int ppi_getall(int fd, int reg) int ppi_setall(int fd, int reg, int val) { unsigned char v; - unsigned long get, set; int rc; - rc = ppi_getops(reg, &get, &set); + v = val; + rc = ppi_shadow_access(fd, reg, &v, PPI_WRITE); + if (rc) return -1; - v = val; - ioctl(fd, set, &v); - return 0; } @@ -196,6 +205,7 @@ int ppi_setall(int fd, int reg, int val) int ppi_open(char * port) { int fd; + unsigned char v; fd = open(port, O_RDWR); if (fd < 0) { @@ -204,6 +214,14 @@ int ppi_open(char * port) return -1; } + /* + * Initialize shadow registers + */ + + ppi_shadow_access (fd, PPIDATA, &v, PPI_READ); + ppi_shadow_access (fd, PPICTRL, &v, PPI_READ); + ppi_shadow_access (fd, PPISTATUS, &v, PPI_READ); + return fd; }