Squidge
Certified Guru
One of the first programs I wrote for gp2x linux was a hardware hacker. It may be useful to others, so here's the code. It allows you to play with all the hardware registers. I used it to find out how to work the lcd registers.
Code:
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
extern int errno;
unsigned long *screendw;
unsigned long *fb0;
unsigned long *fb1;
int Gfxfd;
#define GPIOA 0xC0001180
#define GPIOB 0xC0001182
#define GPIOC 0xC0001184
#define GPIOD 0xC0001186
#define GPIOE 0xC0001188
#define GPIOF 0xC000118A
#define GPIOG 0xC000118C
#define GPIOH 0xC000118E
#define GPIOI 0xC0001190
#define GPIOJ 0xC0001192
#define GPIOK 0xC0001194
#define GPIOL 0xC0001196
#define GPIOM 0xC0001198
#define GPION 0xC000119A
#define GPIOO 0xC000119C
void *trymmap (void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
char *p;
int aa;
printf ("mmap(%X, %X, %X, %X, %X, %X) ... ", (unsigned int)start, length, prot, flags, fd, (unsigned int)offset);
p = mmap (start, length, prot, flags, fd, offset);
if (p == (char *)0xFFFFFFFF)
{
aa = errno;
printf ("failed. errno = %d\n", aa);
}
else
{
printf ("OK! (%X)\n", (unsigned int)p);
}
return p;
}
unsigned short ReadGfx(unsigned short addr)
{
if ((addr % 4) == 0)
{
return (screendw[addr >> 2] & 0xFFFF);
}
else if ((addr % 2) == 0)
{
return (screendw[addr >> 2] >> 16);
}
else
{
printf ("Unaligned read from memory -> C000%X", addr);
return 0;
}
}
void WriteGfx (unsigned short addr, unsigned short data)
{
if ((addr % 4) == 0)
{
screendw[addr >> 2] &= 0xFFFF0000;
screendw[addr >> 2] |= data;
}
else if ((addr % 2) == 0)
{
screendw[addr >> 2] &= 0xFFFF;
screendw[addr >> 2] |= (data << 16);
}
else
{
printf ("Unaligned write to memory -> C000%X with data %X", addr, data);
}
}
unsigned char InitGfx (void)
{
Gfxfd = open("/dev/mem", O_RDWR);
if (Gfxfd == -1)
{
printf ("Open failed\n");
return 0;
}
printf ("/dev/mem opened successfully - fd = %d\n", Gfxfd);
screendw = trymmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, Gfxfd, 0xc0000000);
if (screendw == (unsigned long *)0xFFFFFFFF) return 0;
return 1;
}
void CloseGfx (void)
{
close (Gfxfd);
}
int main(void)
{
int p,q,r = 0;
int haddr = 0xC0000000;
unsigned int *mallocaddr = (unsigned int *)malloc ((320*240)*4);
int fb0fd, fb1fd;
struct fb_fix_screeninfo fb0_fixed, fb1_fixed;
struct fb_var_screeninfo fb0_var, fb1_var;
if (!InitGfx()) return 0;
printf ("mallocaddr is at %X\n\n", (unsigned int)mallocaddr);
fb0fd = open ("/dev/fb/0", O_RDWR);
if (!fb0fd)
{
printf ("/dev/fb/0 open fail\n");
return 0;
}
fb1fd = open ("/dev/fb/1", O_RDWR);
if (!fb0fd)
{
printf ("/dev/fb/1 open fail\n");
return 0;
}
if (ioctl(fb0fd, FBIOGET_FSCREENINFO, &fb0_fixed) == -1)
{
printf ("fb0fd fixed ioctl failed\n");
return 0;
}
if (ioctl(fb0fd, FBIOGET_VSCREENINFO, &fb0_var) == -1)
{
printf ("fb0fd var ioctl failed\n");
return 0;
}
if (ioctl(fb1fd, FBIOGET_FSCREENINFO, &fb1_fixed) == -1)
{
printf ("fb1fd fixed ioctl failed\n");
return 0;
}
if (ioctl(fb1fd, FBIOGET_VSCREENINFO, &fb1_var) == -1)
{
printf ("fb1fd var ioctl failed\n");
return 0;
}
printf ("FB0 Fixed\n---------\n\n ID: %s\n MemStart: 0x%X\n MemLength: 0x%X\n LineLength: %d\n MMIO: %X\n MMIOLen: %X\n Accel: %X\n\n",
fb0_fixed.id, fb0_fixed.smem_start, fb0_fixed.smem_len, fb0_fixed.line_length, fb0_fixed.mmio_start,
fb0_fixed.mmio_len, fb0_fixed.accel);
printf ("FB0 Variable\n------------\n\n X Res: %d\n Y Res: %d\n BPP: %d\n AccelFlags: %X\n vmode: %X\n\n",
fb0_var.xres, fb0_var.yres, fb0_var.bits_per_pixel, fb0_var.accel_flags, fb0_var.vmode);
printf ("FB1 Fixed\n---------\n\n ID: %s\n MemStart: 0x%X\n MemLength: 0x%X\n LineLength: %d\n MMIO: %X\n MMIOLen: %X\n Accel: %X\n\n",
fb1_fixed.id, fb1_fixed.smem_start, fb1_fixed.smem_len, fb1_fixed.line_length, fb1_fixed.mmio_start,
fb1_fixed.mmio_len, fb1_fixed.accel);
printf ("FB1 Variable\n------------\n\n X Res: %d\n Y Res: %d\n BPP: %d\n AccelFlags: %X\n vmode: %X\n\n",
fb1_var.xres, fb1_var.yres, fb1_var.bits_per_pixel, fb1_var.accel_flags, fb1_var.vmode);
fb0 = trymmap(0, fb0_fixed.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, Gfxfd, fb0_fixed.smem_start);
fb1 = trymmap(0, fb1_fixed.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, Gfxfd, fb1_fixed.smem_start);
for (;;)
{
unsigned long qq;
printf ("Enter address: (-1=same as before, -2=gfx mem select, -3=fb0, -4=blank fb0, -5=0x55 fb0, -6=set fb0)\n: 0x%X+",haddr); scanf ("%X", &p);
switch (p)
{
case -2:
haddr = 0xC0000000; break;
case -3:
haddr = fb0; break;
case -4:
memset (fb0, 0x00, fb0_fixed.smem_len); break;
case -5:
memset (fb0, 0x55, fb0_fixed.smem_len); break;
case -6:
printf ("Enter value: "); scanf ("%X", &qq);
for (q = 0; q < fb0_fixed.smem_len/4; q ++)
fb0[q] = qq;
break;
default:
if (p == -1) p = r;
r = p;
if (haddr == 0xC0000000)
{
printf ("\nAddress: 0x%X - Current value is 0x%X\n", haddr + p, ReadGfx(p));
printf ("Enter new value: 0x"); scanf ("%X", &q);
printf ("Address: %X - old value - %X - requested value - %X - new actual value - ", haddr + p, ReadGfx(p), q);
WriteGfx (p, q);
printf ("%X\n\n", ReadGfx(p));
}
else
{
printf ("\nAddress: 0x%X - Current value is 0x%X\n", haddr + p, fb0[p]);
printf ("Enter new value: 0x"); scanf ("%X", &q);
printf ("Address: %X - old value - %X - requested value - %X - new actual value - ", haddr + p, fb0[p], q);
fb0[p] = q;
printf ("%X\n\n", fb0[p]);
}
break;
}
}
CloseGfx();
printf("test complete\n");
return 0;
}