home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / kernel / ioport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  4.0 KB  |  185 lines

  1. /*
  2.  *    linux/kernel/ioport.c
  3.  *
  4.  * This contains the io-permission bitmap code - written by obz, with changes
  5.  * by Linus.
  6.  */
  7.  
  8. #include <linux/sched.h>
  9. #include <linux/kernel.h>
  10. #include <linux/errno.h>
  11. #include <linux/types.h>
  12. #include <linux/ioport.h>
  13.  
  14. static unsigned long ioport_registrar[IO_BITMAP_SIZE] = {0, /* ... */};
  15.  
  16. #define _IODEBUG
  17.  
  18. #ifdef IODEBUG
  19. static char * ios(unsigned long l)
  20. {
  21.     static char str[33] = { '\0' };
  22.     int i;
  23.     unsigned long mask;
  24.  
  25.     for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1)
  26.         str[i] = (l & mask) ? '1' : '0';
  27.     return str;
  28. }
  29.  
  30. static void dump_io_bitmap(void)
  31. {
  32.     int i, j;
  33.     int numl = sizeof(current->tss.io_bitmap) >> 2;
  34.  
  35.     for (i = j = 0; j < numl; ++i)
  36.     {
  37.         printk("%4d [%3x]: ", 64*i, 64*i);
  38.         printk("%s ", ios(current->tss.io_bitmap[j++]));
  39.         if (j < numl)
  40.             printk("%s", ios(current->tss.io_bitmap[j++]));
  41.         printk("\n");
  42.     }
  43. }
  44. #endif
  45.  
  46. /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
  47. asmlinkage void set_bitmap(unsigned long *bitmap,
  48.                            short base, short extent, int new_value)
  49. {
  50.     int mask;
  51.     unsigned long *bitmap_base = bitmap + (base >> 5);
  52.     unsigned short low_index = base & 0x1f;
  53.     int length = low_index + extent;
  54.  
  55.     if (low_index != 0) {
  56.         mask = (~0 << low_index);
  57.         if (length < 32)
  58.                 mask &= ~(~0 << length);
  59.         if (new_value)
  60.             *bitmap_base++ |= mask;
  61.         else
  62.             *bitmap_base++ &= ~mask;
  63.         length -= 32;
  64.     }
  65.  
  66.     mask = (new_value ? ~0 : 0);
  67.     while (length >= 32) {
  68.         *bitmap_base++ = mask;
  69.         length -= 32;
  70.     }
  71.  
  72.     if (length > 0) {
  73.         mask = ~(~0 << length);
  74.         if (new_value)
  75.             *bitmap_base++ |= mask;
  76.         else
  77.             *bitmap_base++ &= ~mask;
  78.     }
  79. }
  80.  
  81. /* Check for set bits in BITMAP starting at BASE, going to EXTENT. */
  82. asmlinkage int check_bitmap(unsigned long *bitmap, short base, short extent)
  83. {
  84.     int mask;
  85.     unsigned long *bitmap_base = bitmap + (base >> 5);
  86.     unsigned short low_index = base & 0x1f;
  87.     int length = low_index + extent;
  88.  
  89.     if (low_index != 0) {
  90.         mask = (~0 << low_index);
  91.         if (length < 32)
  92.                 mask &= ~(~0 << length);
  93.         if (*bitmap_base++ & mask)
  94.             return 1;
  95.         length -= 32;
  96.     }
  97.     while (length >= 32) {
  98.         if (*bitmap_base++ != 0)
  99.             return 1;
  100.         length -= 32;
  101.     }
  102.  
  103.     if (length > 0) {
  104.         mask = ~(~0 << length);
  105.         if (*bitmap_base++ & mask)
  106.             return 1;
  107.     }
  108.     return 0;
  109. }
  110.  
  111. /*
  112.  * this changes the io permissions bitmap in the current task.
  113.  */
  114. asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
  115. {
  116.     if (from + num <= from)
  117.         return -EINVAL;
  118.     if (from + num > IO_BITMAP_SIZE*32)
  119.         return -EINVAL;
  120.     if (!suser())
  121.         return -EPERM;
  122.  
  123. #ifdef IODEBUG
  124.     printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
  125. #endif
  126.     set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
  127.     return 0;
  128. }
  129.  
  130. unsigned int *stack;
  131.  
  132. /*
  133.  * sys_iopl has to be used when you want to access the IO ports
  134.  * beyond the 0x3ff range: to get the full 65536 ports bitmapped
  135.  * you'd need 8kB of bitmaps/process, which is a bit excessive.
  136.  *
  137.  * Here we just change the eflags value on the stack: we allow
  138.  * only the super-user to do it. This depends on the stack-layout
  139.  * on system-call entry - see also fork() and the signal handling
  140.  * code.
  141.  */
  142. asmlinkage int sys_iopl(long ebx,long ecx,long edx,
  143.          long esi, long edi, long ebp, long eax, long ds,
  144.          long es, long fs, long gs, long orig_eax,
  145.          long eip,long cs,long eflags,long esp,long ss)
  146. {
  147.     unsigned int level = ebx;
  148.  
  149.     if (level > 3)
  150.         return -EINVAL;
  151.     if (!suser())
  152.         return -EPERM;
  153.     *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
  154.     return 0;
  155. }
  156.  
  157.  
  158. void snarf_region(unsigned int from, unsigned int num)
  159. {
  160.     if (from > IO_BITMAP_SIZE*32)
  161.         return;
  162.     if (from + num > IO_BITMAP_SIZE*32)
  163.         num = IO_BITMAP_SIZE*32 - from;
  164.     set_bitmap(ioport_registrar, from, num, 1);
  165.     return;
  166. }
  167.  
  168. int check_region(unsigned int from, unsigned int num)
  169. {
  170.     if (from > IO_BITMAP_SIZE*32)
  171.         return 0;
  172.     if (from + num > IO_BITMAP_SIZE*32)
  173.         num = IO_BITMAP_SIZE*32 - from;
  174.     return check_bitmap(ioport_registrar, from, num);
  175. }
  176.  
  177. /* Called from init/main.c to reserve IO ports. */
  178. void reserve_setup(char *str, int *ints)
  179. {
  180.     int i;
  181.  
  182.     for (i = 1; i < ints[0]; i += 2)
  183.         snarf_region(ints[i], ints[i+1]);
  184. }
  185.