linux-old/kernel/resource.c
<<
>>
Prefs
   1/*
   2 *      linux/kernel/resource.c
   3 *
   4 * Copyright (C) 1995   Linus Torvalds
   5 *                      David Hinds
   6 *
   7 * Kernel io-region resource management
   8 */
   9
  10#include <linux/sched.h>
  11#include <linux/kernel.h>
  12#include <linux/errno.h>
  13#include <linux/types.h>
  14#include <linux/ioport.h>
  15#include <linux/init.h>
  16
  17#define IOTABLE_SIZE 128
  18
  19typedef struct resource_entry_t {
  20        u_long from, num;
  21        const char *name;
  22        struct resource_entry_t *next;
  23} resource_entry_t;
  24
  25static resource_entry_t iolist = { 0, 0, "", NULL };
  26
  27static resource_entry_t iotable[IOTABLE_SIZE];
  28
  29/*
  30 * This generates the report for /proc/ioports
  31 */
  32int get_ioport_list(char *buf)
  33{
  34        resource_entry_t *p;
  35        int len = 0;
  36
  37        for (p = iolist.next; (p) && (len < 4000); p = p->next)
  38                len += sprintf(buf+len, "%04lx-%04lx : %s\n",
  39                           p->from, p->from+p->num-1, p->name);
  40        if (p)
  41                len += sprintf(buf+len, "4K limit reached!\n");
  42        return len;
  43}
  44
  45/*
  46 * The workhorse function: find where to put a new entry
  47 */
  48static resource_entry_t *find_gap(resource_entry_t *root,
  49                                  u_long from, u_long num)
  50{
  51        unsigned long flags;
  52        resource_entry_t *p;
  53        
  54        if (from > from+num-1)
  55                return NULL;
  56        save_flags(flags);
  57        cli();
  58        for (p = root; ; p = p->next) {
  59                if ((p != root) && (p->from+p->num-1 >= from)) {
  60                        p = NULL;
  61                        break;
  62                }
  63                if ((p->next == NULL) || (p->next->from > from+num-1))
  64                        break;
  65        }
  66        restore_flags(flags);
  67        return p;
  68}
  69
  70/*
  71 * Call this from the device driver to register the ioport region.
  72 */
  73void request_region(unsigned long from, unsigned long num, const char *name)
  74{
  75        resource_entry_t *p;
  76        int i;
  77
  78        for (i = 0; i < IOTABLE_SIZE; i++)
  79                if (iotable[i].num == 0)
  80                        break;
  81        if (i == IOTABLE_SIZE)
  82                printk("warning: ioport table is full\n");
  83        else {
  84                p = find_gap(&iolist, from, num);
  85                if (p == NULL)
  86                        return;
  87                iotable[i].name = name;
  88                iotable[i].from = from;
  89                iotable[i].num = num;
  90                iotable[i].next = p->next;
  91                p->next = &iotable[i];
  92                return;
  93        }
  94}
  95
  96/* 
  97 * Call this when the device driver is unloaded
  98 */
  99void release_region(unsigned long from, unsigned long num)
 100{
 101        resource_entry_t *p, *q;
 102
 103        for (p = &iolist; ; p = q) {
 104                q = p->next;
 105                if (q == NULL)
 106                        break;
 107                if ((q->from == from) && (q->num == num)) {
 108                        q->num = 0;
 109                        p->next = q->next;
 110                        return;
 111                }
 112        }
 113}
 114
 115/*
 116 * Call this to check the ioport region before probing
 117 */
 118int check_region(unsigned long from, unsigned long num)
 119{
 120        return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
 121}
 122
 123#ifdef __sparc__   /* Why to carry unused code on other architectures? */
 124/*
 125 * This is for architectures with MMU-managed ports (sparc).
 126 */
 127unsigned long occupy_region(unsigned long base, unsigned long end,
 128                            unsigned long num, unsigned int align, const char *name)
 129{
 130        unsigned long from = 0, till;
 131        unsigned long flags;
 132        int i;
 133        resource_entry_t *p;            /* Scanning ptr */
 134        resource_entry_t *p1;           /* === p->next */
 135        resource_entry_t *s;            /* Found slot */
 136
 137        if (base > end-1)
 138                return 0;
 139        if (num > end - base)
 140                return 0;
 141
 142        for (i = 0; i < IOTABLE_SIZE; i++)
 143                if (iotable[i].num == 0)
 144                        break;
 145        if (i == IOTABLE_SIZE) {
 146                /* Driver prints a warning typicaly. */
 147                return 0;
 148        }
 149
 150        save_flags(flags);
 151        cli();
 152        /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
 153        s = NULL;
 154        for (p = &iolist; p != NULL; p = p1) {
 155                p1 = p->next;
 156                /* Find window in list */
 157                from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
 158                till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
 159                /* printk(" %08lx:%08lx", from, till); */
 160                /* Clip window with base and end */
 161                if (from < base) from = base;
 162                if (till > end) till = end;
 163                /* See if result is large enougth */
 164                if (from < till && from + num < till) {
 165                        s = p;
 166                        break;
 167                }
 168        }
 169        /* printk("\r\n"); */
 170        restore_flags(flags);
 171
 172        if (s == NULL)
 173                return 0;
 174
 175        iotable[i].name = name;
 176        iotable[i].from = from;
 177        iotable[i].num = num;
 178        iotable[i].next = s->next;
 179        s->next = &iotable[i];
 180        return from;
 181}
 182#endif
 183
 184/* Called from init/main.c to reserve IO ports. */
 185__initfunc(void reserve_setup(char *str, int *ints))
 186{
 187        int i;
 188
 189        for (i = 1; i < ints[0]; i += 2)
 190                request_region(ints[i], ints[i+1], "reserved");
 191}
 192
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.