//-------------------------------------------------------------------
//	tryioctl.cpp
//
//	This is a 'test program' to show how an application can use
//	the 'ioctl()' function in our 'uhci.c' device-driver module
//	to discover (1) the physical address of our driver's kernel 
//	memory buffer (needed for setting up UHCI data-structures), 
//	(2) the number of UHCI controllers found in the system, and
//	(3) the I/O-port base-addresses for each controller (needed 
//	for reading and writing any of the various UHCI registers).
//
//	In summary, our 'ioctl() function gets called as follows:
//	  command 0 returns kernel-memory's location in variable
//	  command 1 with variable = 0 to get the number of UHCIs		
//	  command 1 with variable > 0 to get a hub's i/o-address
//
//		to compile:  $ g++ tryioctl.cpp -o tryioctl
//		to execute:  $ ./tryioctl
//
//	NOTE: Prior installation of our 'uhci.c' driver is needed.
//
//	programmer: ALLAN CRUSE
//	written on: 24 MAR 2010
//-------------------------------------------------------------------

#include <stdio.h>	// for printf(), perror() 
#include <fcntl.h>	// for open() 
#include <stdlib.h>	// for exit() 
#include <sys/ioctl.h>	// for ioctl()

char devname[] = "/dev/uhci";

int main( int argc, char **argv )
{
	// open our device-file for reading and writing
	int	fd = open( devname, O_RDWR );
	if ( fd < 0 ) { perror( devname ); exit(1); }

	// show the number of UHCI controllers found 
	unsigned long	hub_count = 0L;
	if ( ioctl( fd, 1, &hub_count ) < 0 ) { perror( "ioctl" ); exit(1); }
	printf( "\n Number of UHCI controllers = %lu \n", hub_count );

	// show each controller's I/O-Port Base-Address
	printf( "\n I/O-Port Base-Addresses: \n\n" );
	for (int i = 0; i < hub_count; i++)
		{
		unsigned long	host_addr = i+1L;
		if ( ioctl( fd, 1, &host_addr ) < 0 )
			{ perror( "ioctl" ); exit(1); }
		printf( "      UHCI #%d: ", i+1 );
		printf( " I/O-Base = 0x%04X \n", host_addr );
		}
	
	// show the physical address for the kernel memory allocation
	unsigned long	kmem_addr = 0L;
	if ( ioctl( fd, 0, &kmem_addr ) < 0 ) { perror( "ioctl" ); exit(1); }
	printf( "\n Kernel memory at physical address 0x%08X\n\n", kmem_addr );
}