150 likes | 189 Views
Learn to implement show and hide functions for the SiS 315 cursor in Linux device driver using IOCTL commands. Discover techniques for manipulating cursor visibility and command initiation.
E N D
The ‘ioctl’ driver-function On implementing ‘show’ and ‘hide’ for the SiS 315 hardware cursor
‘struct file_operations’ • For a Linux device-driver’s ‘init_module()’ function, there are two main actions: • Initializing the driver’s global data-structures (this includes verifying the device’s presence) • Registering the driver’s service-functions with the kernel (i.e., the ‘file_operations’ structure) • The driver’s ‘cleanup_module()’ function has the duty to ‘unregister’ those services
Driver services • For character-mode device-drivers (such as our ‘dram.c’, ‘mbr.c’, and ‘vramm.c’), we have implemented some (or all) of the following service-functions (i.e., ‘methods’) • read() • llseek() • write() • mmap()
The ‘file’ paradigm • The UNIX approach to device-control is to create objects that represent i/o-devices, but which behave like ‘files’ do, insofar as the application programmer is concerned • So ‘read()’, ‘llseek()’, ‘write()’ and ‘mmap() use the same function-call syntax – and in most respects the same semantics – for both ‘files’ and ‘devices’
An imperfect paradigm • But often there are a few ways in which the file-object paradigm doesn’t quite fit with important features of an i/o device • In these cases, device-drivers can provide a ‘workaround’ that allows applications to perform device-actions that deviate from customary ‘read/write/seek’ file-like actions • This ‘workaround’ mechanism is ‘ioctl()’
The graphics display • Our PC’s graphics display device offers an easy example of desirable behavior that is outside the traditional ‘file’ paradigm • In order to display graphical images that are full-screen renderings of artistic work, we want to avoid seeing a mouse-cursor (it’s an ugly and disruptive and distraction) • How can a program ‘turn off’ that cursor?
The GPU ‘resources’ • The SiS 315 graphics processing units in our workstations are each equipped with 32-megabytes of video display memory (designated as PCI resource 0) • These graphics adapters also implement a set of memory-mapped registers known as the 2D graphics engine (and designated as PCI resource 1)
‘pci_resource_start()’ • Device-drivers can use this Linux kernel function to discover the physical address where resource 0, or resource 1, resides struct pci_dev *devp = NULL: devp = pci_find_device( VEN, DEV, devp ); vram = pci_resource_start( devp, 0 ); mmio = pci_resource_start( devp, 1 );
SiS 315 information • Programming manual for the SiS 315 GPU is not usually made available to the public • But some information can be derived from reading Linux device-driver source-code • Examples are: • The ‘/usr/src/linux/drivers/video/sis’ directory • Also download the ‘svgalib-1.9.17’ package
Graphics Cursor 31 30 0 cursor-image source-offset 0x8500 cursor visibility control bit: 0=hide, 1=show cursor starting command bit: 0=no, 1=yes cursor-image horizontal coordinate 0x850C cursor-image vertical coordinate 0x8510
Algorithm to hide cursor • Map physical page containing the registers to a virtual address (with ‘ioremap()’) • Read current values of these registers • Clear bit #30 (to make cursor invisible) • Set bit #31 (to initiate a new command) • Write these adjusted register values • Undo the mapping (with ‘iounmap()’)
Algorithm to show cursor • Map physical page containing the registers to a virtual address (with ‘ioremap()’) • Read current values of these registers • Set bit #30 (to make cursor visible) • Set bit #31 (to initiate a new command) • Write these adjusted register values • Undo the mapping (with ‘iounmap()’)
The ‘ioctl.c’ module • These techniques are demonstrated in this device-driver module’s ‘ioctl()’ function • Two IOCTL commands are implemented • #define CURSOR_HIDE 0 • #define CURSOR_SHOW 1 • Applications can open the device-file, then use an ioctl-command; for example: int fd = open( “/dev/vram”, O_RDWR ); ioctl( fd, CURSOR_HIDE);
In-class exercise #1 • Try adding new IOCTL commands to the ‘ioctl.c’ driver which lets applications find or move the cursor’s screen-position; #define CURSOR_FIND 2 #define CURSOR_MOVE 3 struct { long x, y; } location; ioctl( fd, CURSOR_FIND, &location ); location.x += 40; location.y += 40; ioctl( fd, CURSOR_MOVE, &location );
In-class exercise #2 • We are not told what function is served by two of the SiS engine’s i/o locations: • 0x8500 (longword) cursor-image source-offset • 0x8504 (longword) <??? Unknown ???> • 0x8508 (longword) <??? Unknown ???> • 0x850C (longword) cursor-image horiz-coord • 0x8510 (longword) cursor-image vertl-coord • So can you ‘discover’ their purpose?