#include <stdio.h>
#include <errno.h>
#include <linux/ioctl.h>

#define ATY_MIRROR_LCD_ON	0x00000001
#define ATY_MIRROR_CRT_ON	0x00000002

#define __u32 unsigned int

/* out param: u32*	backlight value: 0 to 15 */
#define FBIO_ATY128_GET_MIRROR	_IOR('@', 1, sizeof(__u32*))
/* in param: u32*	backlight value: 0 to 15 */
#define FBIO_ATY128_SET_MIRROR	_IOW('@', 2, sizeof(__u32*))

static void
usage(void)
{
	printf("syntax: m3mirror [crt:0|1] [lcd:0|1]\n");
}

main(int ac, char **av)
{
	int fd, rc, i;
	unsigned long value, orig;

	printf("ATI Rage M3 mirror tool, v0.1\n");
	fd = open("/dev/fb0", 0);
	if (fd < 0) {
		perror("open /dev/fb0");
		exit(1);
	}
	rc = ioctl(fd, FBIO_ATY128_GET_MIRROR, &value);
	if (rc != 0) {
		printf("error %d getting mirror value\n");
		goto bail;
	}
	printf("Mirror is currently: lcd: %s, crt: %s\n",
		(value & ATY_MIRROR_LCD_ON) ? "on" : "off",
		(value & ATY_MIRROR_CRT_ON) ? "on" : "off");
	orig = value;
	for(i=1; i<ac; i++) {
		if (!strncmp(av[i], "lcd:", 4)) {
			if (atoi((av[i])+4))
				value |= ATY_MIRROR_LCD_ON;
			else
				value &= ~ATY_MIRROR_LCD_ON;
		} else if (!strncmp(av[i], "crt:", 4)) {
			if (atoi((av[i])+4))
				value |= ATY_MIRROR_CRT_ON;
			else
				value &= ~ATY_MIRROR_CRT_ON;
		} else {
			usage();
			rc = -EINVAL;
			goto bail;
		}
	}
	if (orig != value) {
		rc = ioctl(fd, FBIO_ATY128_SET_MIRROR, &value);
		if (rc != 0) {
			printf("error %d setting mirror value\n");
			exit(rc);
		}
		printf("Mirror is now: lcd: %s, crt: %s\n",
			(value & ATY_MIRROR_LCD_ON) ? "on" : "off",
			(value & ATY_MIRROR_CRT_ON) ? "on" : "off");
	}
bail:
	close(fd);	
	exit(rc);
}
