*ppi.c: Major speed-tuning. Since ioctl() is expensive read from shadow-registers where possible.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@384 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Jan-Hinnerk Reichert 2003-11-22 03:31:27 +00:00
parent eed95a739d
commit a26bd26c9e
1 changed files with 63 additions and 45 deletions

108
ppi.c
View File

@ -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;
}