AGPGART_IO(4I) Ioctl Requests AGPGART_IO(4I)

NAME


agpgart_io - Solaris agpgart driver I/O control operations

SYNOPSIS


#include <sys/agpgart.h>


DESCRIPTION


The Accelerated Graphics Port (AGP) is a PCI bus technology
enhancement that improves 3D graphics performance by using low-cost
system memory. AGP chipsets use the Graphics Address Remapping Table
(GART) to map discontiguous system memory into a contiguous PCI
memory range (known as the AGP Aperture), enabling the graphics card
to utilize the mapped aperture range as video memory.


The agpgart driver creates a pseudo device node at /dev/agpgart and
provides a set of ioctls for managing allocation/deallocation of
system memory, setting mappings between system memory and aperture
range, and setting up AGP devices. The agpgart driver manages both
pseudo and real device nodes, but to initiate AGP-related operations
you operate only on the /dev/agpgart pseudo device node. To do this,
open /dev/agpgart. The macro defined for the pseudo device node name
is:

#define AGP_DEVICE "/dev/agpgart"


The agpgart_io driver implementation is AGP architecture-dependent
and cannot be made generic. Currently, the agpgart_io driver only
supports specific AGP systems. To determine if a system is
supported, run an open(2) system call on the AGP_DEVICE node. (Note
that open(2) fails if a system is not supported). After the
AGP_DEVICE is opened, you can use kstat(8) to read the system
architecture type.


In addition to AGP system support, the agpgart ioctls can also be
used on Intel integrated graphics devices (IGD). IGD devices usually
have no dedicated video memory and must use system memory as video
memory. IGD devices contain translation tables (referred to as GTT
tables) that are similar to the GART translation table for address
mapping purposes.


Processes must open the agpgart_io driver utilizing a GRAPHICS_ACCESS
privilege. Then all the ioctls can be called by this processes with
the saved file descriptor. With the exception of AGPIOC_INFO, the
AGPIOC_ACQUIRE ioctl must be called before any other ioctl. Once a
process has acquired GART, it cannot be acquired by another process
until the former process calls AGPIOC_RELEASE.


If the AGP_DEVICE fails to open, it may be due to one of the
following reasons:

EAGAIN

GART table allocation failed.


EIO

Internal hardware initialization failed.


ENXIO

Getting device soft state error. (This is unlikely to happen.)


EPERM

Without enough privilege.


IOCTLS


With the exception of GPIOC_INFO, all ioctls shown in this section
are protected by GRAPHICS_ACCESS privilege. (Only processes with
GRAPHICS_ACCESS privilege in its effective set can access the
privileged ioctls).


Common ioctl error codes are shown below. (Additional error codes may
be displayed by individual ioctls.)

ENXIO

Ioctl command not supported or getting device soft state error.


EPERM

Process not privileged.


AGPIOC_INFO

Get system wide AGP or IGD hardware information. This command can
be called by any process from user or kernel context.

The argument is a pointer to agp_info_t structure.

typedef struct _agp_info {
agp_version_t agpi_version; /* OUT: AGP version supported */
uint32_t agpi_devid; /* OUT: bridge vendor + device */
uint32_t agpi_mode; /* OUT: mode of bridge */
ulong_t agpi_aperbase; /* OUT: base of aperture */
size_t agpi_apersize; /* OUT: aperture size in MB */
uint32_t agpi_pgtotal; /* OUT: max aperture pages avail. */
uint32_t agpi_pgsystem; /* OUT: same as pg_total */
uint32_t agpi_pgused; /* OUT: no. of currently used pages */
} agp_info_t;

agpi_version The version of AGP protocol the bridge device is
compatible with, for example, major 3 and minor 0
means AGP version 3.0.

typedef struct _agp_version {
uint16_t agpv_major;
uint16_t agpv_minor;
} agp_version_t;

agpi_devid AGP bridge vendor and device ID.
agpi_mode Current AGP mode, read from AGP status register of
target device. The main bits are defined as below.
/* AGP status register bits definition */

#define AGPSTAT_RQ_MASK 0xff000000
#define AGPSTAT_SBA (0x1 << 9)
#define AGPSTAT_OVER4G (0x1 << 5)
#define AGPSTAT_FW (0x1 << 4)
#define AGPSTAT_RATE_MASK 0x7
/* AGP 3.0 only bits */
#define AGPSTAT_ARQSZ_MASK (0x7 << 13)
#define AGPSTAT_CAL_MASK (0x7 << 10)
#define AGPSTAT_GART64B (0x1 << 7)
#define AGPSTAT_MODE3 (0x1 << 3)
/* rate for 2.0 mode */
#define AGP2_RATE_1X 0x1
#define AGP2_RATE_2X 0x2
#define AGP2_RATE_4X 0x4
/* rate for 3.0 mode */
#define AGP3_RATE_4X 0x1
#define AGP3_RATE_8X 0x2

agpi_aperbase The base address of aperture in PCI memory space.
agpi_apersize The size of the aperture in megabytes.
agpi_pgtotal Represents the maximum memory
pages the system can allocate
according to aperture size and
system memory size (which may differ
from the maximum locked memory a process
can have. The latter is subject
to the memory resource limit imposed
by the resource_controls(7) for each
project(5)):

project.max-device-locked-memory

This value can be modified through system
utilities like prctl(1).

agpi_pgsystem Same as pg_total.
agpi_pgused System pages already allocated by the driver.

Return Values:

EFAULT Argument copy out error
EINVAL Command invalid
0 Success


AGPIOC_ACQUIRE

Acquire control of GART. With the exception of AGPIOC_INFO, a
process must acquire GART before can it call other agpgart ioctl
commands. Additionally, only processes with GRAPHICS_ACCESS
privilege may access this ioctl. In the current agpgart
implementation, GART access is exclusive, meaning that only one
process can perform GART operations at a time. To release control
over GART, call AGPIOC_RELEASE. This command can be called from
user or kernel context.

The argument should be NULL.

Return values:

EBUSY
GART has been acquired


0
Success.


AGPIOC_RELEASE

Release GART control. If a process releases GART control, it
cannot perform additional GART operations until GART is
reacquired. Note that this command does not free allocated memory
or clear GART entries. (All clear jobs are done by direct calls
or by closing the device). When a process exits without making
this ioctl, the final close(2) performs this automatically. This
command can be called from user or kernel context.

The argument should be NULL.

Return values:

EPERM
Not owner of GART.


0
Success.


AGPIOC_SETUP

Setup AGPCMD register. An AGPCMD register resides in both the
AGP master and target devices. The AGPCMD register controls the
working mode of the AGP master and target devices. Each device
must be configured using the same mode. This command can be
called from user or kernel context.

The argument is a pointer to agp_setup_t structure:

typedef struct _agp_setup {
uint32_t agps_mode; /* IN: value to be set for AGPCMD */
} agp_setup_t;

agps_mode Specifying the mode to be set. Each bit of the value may have
a specific meaning, please refer to AGP 2.0/3.0 specification
or hardware datasheets for details.

/* AGP command register bits definition */
#define AGPCMD_RQ_MASK 0xff000000
#define AGPCMD_SBAEN (0x1 << 9)
#define AGPCMD_AGPEN (0x1 << 8)
#define AGPCMD_OVER4GEN (0x1 << 5)
#define AGPCMD_FWEN (0x1 << 4)
#define AGPCMD_RATE_MASK 0x7
/* AGP 3.0 only bits */
#define AGP3_CMD_ARQSZ_MASK (0x7 << 13)
#define AGP3_CMD_CAL_MASK (0x7 << 10)
#define AGP3_CMD_GART64BEN (0x1 << 7)

The final values set to the AGPCMD register of the master/target
devices are decided by the agps_mode value and AGPSTAT of the
master and target devices.

Return Values:

EPERM
Not owner of GART.


EFAULT
Argument copy in error.


EINVAL
Command invalid for non-AGP system.


EIO
Hardware setup error.


0
Success.


AGPIOC_ALLOCATE

Allocate system memory for graphics device. This command returns
a unique ID which can be used in subsequent operations to
represent the allocated memory. The memory is made up of
discontiguous physical pages. In rare cases, special memory types
may be required. The allocated memory must be bound to the GART
table before it can be used by graphics device. Graphics
applications can also mmap(2) the memory to userland for data
storing. Memory should be freed when it is no longer used by
calling AGPIOC_DEALLOCATE or simply by closing the device. This
command can be called from user or kernel context.

The argument is a pointer to agp_allocate_t structure.

typedef struct _agp_allocate {
int32_t agpa_key; /* OUT:ID of allocated memory */
uint32_t agpa_pgcount;/* IN: no. of pages to be allocated */
uint32_t agpa_type;/* IN: type of memory to be allocated */
uint32_t agpa_physical; /* OUT: reserved */
} agp_allocate_t;


agpa_key
Unique ID of the allocated memory.


agpa_pgcount
Number of pages to be allocated. The driver
currently supports only 4K pages. The value
cannot exceed the agpi_pgtotal value
returned by AGPIOC_INFO ioct and is subject
to the limit of project.max-device-locked-
memory. If the memory needed is larger than
the resource limit but not larger than
agpi_pgtotal, use prctl(1) or other system
utilities to change the default value of
memory resource limit beforehand.


agpa_type
Type of memory to be allocated. The valid
value of agpa_type should be AGP_NORMAL. It
is defined as:

#define AGP_NORMAL 0

Above, AGP_NORMAL represents the
discontiguous non-cachable physical memory
which doesn't consume kernel virtual space
but can be mapped to user space by mmap(2).
This command may support more type values in
the future.


agpa_physical
Reserved for special uses. In normal
operations, the value is undefined.

Return Values:

EPERM
Not owner of GART.


EINVAL
Argument not valid.


EFAULT
Argument copy in/out error.


ENOMEM
Memory allocation error.


0
Success.


AGPIOC_DEALLOCATE
Deallocate the memory identified by a key
assigned in a previous allocation. If the
memory isn't unbound from GART, this command
unbinds it automatically. The memory should
no longer be used and those still in mapping
to userland cannot be deallocated. Always
call AGPIOC_DEALLOCATE explicitly (instead
of deallocating implicitly by closing the
device), as the system won't carry out the
job until the last reference to the device
file is dropped. This command from user or
kernel context.

The input argument is a key of type int32_t,
no output argument.

Return Values:

EPERM
Not owner of GART.


EINVAL
Key not valid or memory in use.


0
Success.


AGPIOC_BIND
Bind allocated memory. This command binds
the allocated memory identified by a key
to a specific offset of the GART table,
which enables GART to translate the
aperture range at the offset to system
memory. Each GART entry represents one
physical page. If the GART range is
previously bound to other system memory, it
returns an error. Once the memory is bound,
it cannot be bound to other offsets unless
it is unbound. To unbind the memory, call
AGPIOC_UNBIND or deallocate the memory. This
command can be called from user or kernel
context.

The argument is a pointer to agp_bind_t structure:

typedef struct _agp_bind {
int32_t agpb_key; /* IN: ID of memory to be bound */
uint32_t agpb_pgstart; /* IN: offset in aperture */
} agp_bind_t;


agpb_key
The unique ID of the
memory to be bound,
which is previously
allocated by calling
AGPIOC_ALLOCATE.


agpb_pgstart
The starting page offset
to be bound in aperture
space.

Return Values:

EPERM
Not owner of GART.


EFAULT
Argument copy in error.


EINVAL
Argument not valid.


EIO
Binding to the GTT table
of IGD devices failed.


0
Success.


AGPIOC_UNBIND
Unbind memory identified by a key from the
GART. This command clears the corresponding
entries in the GART table. Only the memory
not in mapping to userland is allowed to be
unbound.

This ioctl command can be called from user
or kernel context.

The argument is a pointer to agp_unbind_t structure.

typedef struct _agp_unbind {
int32_t agpu_key; /* IN: key of memory to be unbound*/
uint32_t agpu_pri; /* Not used: for compat. with Xorg */
} agp_unbind_t;


agpu_key
Unique ID of the memory
to be unbound which was
previously bound by
calling AGPIOC_BIND.


agpu_pri
Reserved for
compatibility with
X.org/XFree86, not used.

Return Values:

EPERM
Not owner of GART.


EFAULT
Argument copy in error.


EINVAL
Argument not valid or
memory in use.


EIO
Unbinding from the GTT
table of IGD devices
failed.


0
Success


EXAMPLE


Below is an sample program showing how agpgart ioctls can be used:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h
#include <sys/ioccom.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/agpgart.h>

#define AGP_PAGE_SIZE 4096

int main(int argc, char *argv[])
{
int fd, ret;
agp_allocate_t alloc;
agp_bind_t bindinfo;
agp_info_t agpinfo;
agp_setup_t modesetup;
int *p = NULL;
off_t mapoff;
size_t maplen;

if((fd = open(AGP_DEVICE, O_RDWR))== -1) {
printf("open AGP_DEVICE error with %d\n", errno);\
exit(-1);
}
printf("device opened\n");

ret = ioctl(fd, AGPIOC_INFO, &agpinfo);
if(ret == -1) {
printf("Get info error %d\n", errno);
exit(-1);
}
printf("AGPSTAT is %x\n", agpinfo.agpi_mode);
printf("APBASE is %x\n", agpinfo.agpi_aperbase);
printf("APSIZE is %dMB\n", agpinfo.agpi_apersize);
printf("pg_total is %d\n", agpinfo.agpi_pgtotal);

ret = ioctl(fd, AGPIOC_ACQUIRE);
if(ret == -1) {
printf(" Acquire GART error %d\n", errno);
exit(-1);
}

modesetup.agps_mode = agpinfo.agpi_mode;
ret = ioctl(fd, AGPIOC_SETUP, &modesetup);
if(ret == -1) {
printf("set up AGP mode error\n", errno);
exit(-1);
}

printf("Please input the number of pages you want to allocate\n");
scanf("%d", &alloc.agpa_pgcount);
alloc.agpa_type = AGP_NORMAL;
ret = ioctl(fd, AGPIOC_ALLOCATE, &alloc);
if(ret == -1) {
printf("Allocate memory error %d\n", errno);
exit(-1);
}

printf("Please input the aperture page offset to bind\n");
scanf("%d", &bindinfo.agpb_pgstart);
bindinfo.agpb_key = alloc.agpa_key;
ret = ioctl(fd, AGPIOC_BIND, &bindinfo);
if(ret == -1) {
printf("Bind error %d\n", errno);
exit(-1);
}
printf("Bind successful\n");

/*
* Now gart aperture space from (bindinfo.agpb_pgstart) to
* (bindinfo.agpb_pgstart + alloc.agpa_pgcount) can be used for
* AGP graphics transactions
*/
...

/*
* mmap can allow user processes to store graphics data
* to the aperture space
*/
maplen = alloc.agpa_pgcount * AGP_PAGE_SIZE;
mapoff = bindinfo.agpb_pgstart * AGP_PAGE_SIZE;
p = (int *)mmap((caddr_t)0, maplen, (PROT_READ | PROT_WRITE),
MAP_SHARED, fd, mapoff);
if (p == MAP_FAILED) {
printf("Mmap error %d\n", errno);
exit(-1);
}
printf("Mmap successful\n");
...

/*
* When user processes finish access to the aperture space,
* unmap the memory range
*/
munmap((void *)p, maplen);
...

/*
* After finishing AGP transactions, the resources can be freed
* step by step or simply by close device.
*/
ret = ioctl(fd, AGPIOC_DEALLOCATE, alloc.agpa_key);
if(ret == -1) {
printf(" Deallocate memory error %d\n", errno);
exit(-1);
}

ret = ioctl(fd, AGPIOC_RELEASE);
if(ret == -1) {
printf(" Release GART error %d\n", errno);
exit(-1);
}

close(fd);
}


FILES


/dev/agpgart

Symbolic link to the pseudo agpgart device.


/kernel/drv/amd64/agpgart

agpgart pseudo driver.


/kernel/drv/agpgart.conf

Driver configuration file.


ATTRIBUTES


See attributes(7) for descriptions of the following attributes:


+----------------+-----------------+
|ATTRIBUTE TYPE | ATTRIBUTE VALUE |
+----------------+-----------------+
|Architecture | X86 |
+----------------+-----------------+
|Stability level | Unstable |
+----------------+-----------------+

SEE ALSO


prctl(1), kstat(8), close(2), ioctl(2), open(2), mmap(2), project(5),
privileges(7), attributes(7), resource_controls(7)

September 10, 2013 AGPGART_IO(4I)

tribblix@gmail.com :: GitHub :: Privacy