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