The ‘ioctl’ driver-function On implementing ‘show’ and ‘hide’

advertisement
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
0x8500
0
cursor-image source-offset
cursor visibility control bit: 0=hide, 1=show
cursor starting command bit: 0=no, 1=yes
0x850C
cursor-image horizontal coordinate
0x8510
cursor-image vertical coordinate
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
– #define CURSOR_SHOW
0
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?
Download