RFC: Resource Management

Andrew Mileski (dmtech@magi.com)
Tue, 13 Feb 1996 18:37:14 -0500 (EST)


I'd like to hear comments on the following. Thanks.

Note: I have the completed code for all this (untested).

-- Andrew E. Mileski --
-------------------------------------------------------
mailto:dmtech@magi.com http://www.magi.com/~dmtech/

Improved Hardware Resource Management
=====================================
- All hardware resources (DMA, I/O, IRQ, memory) are allocated through
a common kernel API.
- Any number and mixture of resources, in any order, can be requested
or released in a single call.
- All resources in use are reported under the proc fs.

Share and Play Nice! - The Golden Rules
====================
1) Don't access any resource you haven't successfully requested.
This includes both READ and WRITE operations.

2) Resources are _PRECIOUS_ and _LIMITED_, so release them whenever
they are not immediately needed.

API Details
===========
Resource regions that have the same name and are adjacent, are merged into
a single contiguous resource region at request time. Releasing any subset of
a resource region is allowed.

Should the resource info table overflow, the request/release operation
succeeds with a kernel message. This is "A Bad Thing (tm)", and the system
may fail to operate properly, or even panic after such an error. The default
table size can be enlarged by increasing MAX_REGIONS (default = 256) in the
file "linux/kernel/hwres.c". Note that all resources share this table!

int request_hw_region( uint first, uint num, const char *name, int type );
int release_hw_region( uint first, uint num, int type );
- Returns 0 on success, and either -EINVAL or -EBUSY on failure.
- It is important that no attempt be made to release a region that has not
been successfully requested.

hwres_t * request_hw_resources( hwres_t *table, const char *name );
hwres_t * release_hw_resources( hwres_t *table );
- Both return a pointer to the first HWRES_END entry in the table (required).
- The 'failed' member of hdwres_t is the return code for each operation.
- The 'failed' member of first HWRES_END entry applies to all operations.
- Entries that have a non-zero 'failed' member are ignored on release.

Basic Resource Type Description
------------------- -----------
HWRES_DMA Specify DMA channel(s)
HWRES_IO Specify I/O port(s)
HWRES_IRQ Specify IRQ line(s)
HWRES_MEM Specify memory address(es)

Extended Resource Type Description
---------------------- ------------
HWRES_BMF Set the base/mask/flags values

This affects all operations of the type of the following resource entry.
The base/mask/flags are reset to 0 when a different resource type is found.
It can be reversed or changed by another HWRES_BMF entry when necessary.

base = base 'from' value (following entries use an offset from this value).
mask = bit mask for allocating multiple resources (currently unused).
flags = miscellaneous usage (currently unused).

Usage Example - This is only one of the many ways to handle resources.
=============
static hwres_t res_table = {
/* Prefered Configuration */
{ HWRES_IO , 0x00000400, 0x00000010 },
{ HWRES_IO , 0x00000500, 0x00000010 },
{ HWRES_DMA, 0x00000005, 0x00000005 },
{ HWRES_IRQ, 0x0000000b, 0x0000000b },
{ HWRES_MEM, 0x000d0000, 0x000d7fff },
{ HWRES_END },
/* Alternate Configuration 1 */
{ HWRES_IO , 0x00000400, 0x00000010 },
{ HWRES_IO , 0x00000500, 0x00000010 },
{ HWRES_END },
/* Alternate Configuration 2 */
{ HWRES_MEM, 0x000d0000, 0x000d7fff },
{ HWRES_END },
{ HWRES_END }
};

static const char *driver_name = "SuperDuperDriver";

/*
* Request some resources - returns the configuration used.
*/
hwres_t * Do_Request( void )
{
hwres_t *p;

/* Try to use one of the resource configurations */
for ( p = res_table; p->type != HWRES_END; p++ ) {
if ( request_hw_resources( p, driver_name ) == 0 )
break;
p = release_hw_resources( p , driver_name );
}

if ( p->type = HWRES_END )
printk( KERN_ERROR "Could not request resources\n" );

return p;
}

Typical Proc Info Examples
==========================
File: /proc/dma
0x00000002-0x00000002 : fd0
0x00000004-0x00000004 : cascade

File: /proc/ioports
0x00000000-0x0000001f : dma0
0x00000020-0x0000003f : pic0
0x00000040-0x0000005f : timer
0x00000060-0x0000006f : keyboard
0x00000070-0x0000007f : rtc
0x00000080-0x0000009f : dma page
0x000000a0-0x000000bf : pic1
0x000000c0-0x000000df : dma1
0x000000f0-0x000000ff : fpu
0x000001f0-0x000001f8 : hd
0x00000200-0x00000207 : joystick
0x00000278-0x0000027f : lp1
0x000002f8-0x000002ff : serial1
0x00000378-0x0000037f : lp0

File: /proc/interrupts
0x00000000-0x00000000 : timer
0x00000001-0x00000001 : keyboard
0x00000002-0x00000002 : cascade
0x00000003-0x00000003 : serial1
0x00000004-0x00000004 : serial0
0x00000005-0x00000005 : lp1
0x00000008-0x00000008 : rtc
0x00000006-0x00000006 : fd
0x00000007-0x00000007 : lp0
0x0000000d-0x0000000d : fpu
0x0000000e-0x0000000e : hd

File: /proc/address
0x00000000-0x0009ffff : ram
0x000a0000-0x000bffff : video ram
0x000c0000-0x000c7fff : video bios
0x000f0000-0x000fffff : system bios
0x00100000-0x00ffffff : ram
0xc0000000-0xc03fffff : video ram