pciregions.c
上传用户:wudi5211
上传日期:2010-01-21
资源大小:607k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * pciregions.c --  a module that prints address regions of PCI boards
  3.  *
  4.  * Tested with 1.2 on the x86
  5.  * Tested with 2.0 on the x86
  6.  *
  7.  * Copyright (C) 1997   rubini@linux.it (Alessandro Rubini)
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify
  10.  *   it under the terms of the GNU General Public License as published by
  11.  *   the Free Software Foundation; either version 2 of the License, or
  12.  *   (at your option) any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful,
  15.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *   GNU General Public License for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #ifndef __KERNEL__
  24. #  define __KERNEL__
  25. #endif
  26. #ifndef MODULE
  27. #  define MODULE
  28. #endif
  29. #define __NO_VERSION__ /* don't define kernel_verion in module.h */
  30. #include <linux/module.h>
  31. #include <linux/version.h>
  32. char kernel_version [] = UTS_RELEASE;
  33. #include <linux/sched.h>
  34. #include <linux/delay.h>
  35. #include <linux/proc_fs.h>
  36. #include <linux/bios32.h> /* pcibios_* */
  37. #include <linux/pci.h>
  38. /*
  39.  * Refuse to compile under versions older than 1.99.4
  40.  */
  41. #define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) )
  42. #if LINUX_VERSION_CODE < VERSION_CODE(1,99,4)
  43. #  error "This module needs Linux 1.99.4 or newer"
  44. #else
  45. static u32 addresses[] = {
  46.     PCI_BASE_ADDRESS_0,
  47.     PCI_BASE_ADDRESS_1,
  48.     PCI_BASE_ADDRESS_2,
  49.     PCI_BASE_ADDRESS_3,
  50.     PCI_BASE_ADDRESS_4,
  51.     PCI_BASE_ADDRESS_5,
  52.     0
  53. };
  54. int pciregions_read_proc(char *buf, char **start, off_t offset,
  55.                    int len, int unused)
  56. {
  57.     int i, pos=0;
  58.     int bus, fun;
  59.     unsigned char headertype=0;
  60.     u32 id32;
  61.     u16 vendorid, deviceid;
  62.     #define PRINTF(fmt, args...) sprintf(buf+len, fmt, ## args)
  63.     len=0;
  64.     /* Loop through the devices (code not printed in the book) */
  65.     if (!pcibios_present())
  66.         return sprintf(buf,"No PCI bios presentn");
  67.     /*
  68.      * This code is derived from "drivers/pci/pci.c". This means that
  69.      * the GPL applies to this source file and credit is due to the
  70.      * original authors (Drew Eckhardt, Frederic Potter, David
  71.      * Mosberger-Tang)
  72.      */
  73.     bus=0; /* only bus 0 :-) */
  74.     for (fun=0; fun < 0x100 && pos < PAGE_SIZE; fun++) {
  75.         if (!PCI_FUNC(fun)) /* first function */
  76.             pcibios_read_config_byte(bus,fun,PCI_HEADER_TYPE,&headertype);
  77.             else if (!(headertype&0x80))
  78.                 continue;
  79.         pcibios_read_config_dword(bus,fun,PCI_VENDOR_ID, &id32);
  80.         if (!id32 || id32==~0) {
  81.             headertype=0; continue;
  82.         }
  83.         
  84.         if (len > PAGE_SIZE - 1024) /* a big margin, just to be sure */
  85.             return len;
  86.         pcibios_read_config_word(bus,fun,PCI_VENDOR_ID,&vendorid);
  87.         pcibios_read_config_word(bus,fun,PCI_DEVICE_ID,&deviceid);
  88.         /* A device was found: print its regions */
  89.         len += PRINTF("Bus %i, device %2i, fun %2i (id %04x-%04x)n",
  90.                        bus, fun>>3, fun & 7, vendorid, deviceid);
  91.         for (i=0; addresses[i]; i++) {
  92.             u32 curr, mask;
  93.             char *type;
  94.             pcibios_read_config_dword(bus,fun,addresses[i],&curr);
  95.             cli();
  96.             pcibios_write_config_dword(bus,fun,addresses[i],~0);
  97.             pcibios_read_config_dword(bus,fun,addresses[i],&mask);
  98.             pcibios_write_config_dword(bus,fun,addresses[i],curr);
  99.             sti();
  100.             
  101.             len += PRINTF("tregion %i: mask 0x%08lx, now at 0x%08lxn", i,
  102.                            (unsigned long)mask,
  103.                            (unsigned long)curr);
  104.             if (!mask) {
  105.                 len += PRINTF("tregion %i not existentn", i);
  106.                 break;
  107.             }
  108.             /* extract the type, and the programmable bits */
  109.             if (mask & PCI_BASE_ADDRESS_SPACE) {
  110.                 type = "I/O"; mask &= PCI_BASE_ADDRESS_IO_MASK;
  111.             } else {
  112.                 type = "mem"; mask &= PCI_BASE_ADDRESS_MEM_MASK;
  113.             }
  114.             len += PRINTF("tregion %i: type %s, size %in", i,
  115.                           type, ~mask+1);
  116.         }
  117.     } /* fun */
  118.     return len;
  119. }
  120. struct proc_dir_entry pciregions_proc_entry = {
  121.         0,                 /* low_ino: the inode -- dynamic */
  122.        10, "pciregions",   /* len of name and name */
  123.         S_IFREG | S_IRUGO, /* mode */
  124.         1, 0, 0,           /* nlinks, owner, group */
  125.         0, NULL,           /* size - unused; operations -- use default */
  126.         &pciregions_read_proc,   /* function used to read data */
  127.         /* nothing more */
  128.     };
  129. int init_module(void)
  130. {
  131.     proc_register_dynamic(&proc_root, &pciregions_proc_entry);
  132.     return 0;
  133. }
  134. void cleanup_module(void)
  135. {
  136.     proc_unregister(&proc_root, pciregions_proc_entry.low_ino);
  137.     return;
  138. }
  139. #endif /* version 1.99.4 or newer */