Annotation of embedaddon/pciutils/lib/proc.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Library -- Configuration Access via /proc/bus/pci
                      3:  *
                      4:  *     Copyright (c) 1997--2003 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #define _GNU_SOURCE
                     10: 
                     11: #include <stdio.h>
                     12: #include <string.h>
                     13: #include <unistd.h>
                     14: #include <errno.h>
                     15: #include <fcntl.h>
                     16: #include <sys/types.h>
                     17: 
                     18: #include "internal.h"
                     19: #include "pread.h"
                     20: 
                     21: static void
                     22: proc_config(struct pci_access *a)
                     23: {
                     24:   pci_define_param(a, "proc.path", PCI_PATH_PROC_BUS_PCI, "Path to the procfs bus tree");
                     25: }
                     26: 
                     27: static int
                     28: proc_detect(struct pci_access *a)
                     29: {
                     30:   char *name = pci_get_param(a, "proc.path");
                     31: 
                     32:   if (access(name, R_OK))
                     33:     {
                     34:       a->warning("Cannot open %s", name);
                     35:       return 0;
                     36:     }
                     37:   a->debug("...using %s", name);
                     38:   return 1;
                     39: }
                     40: 
                     41: static void
                     42: proc_init(struct pci_access *a)
                     43: {
                     44:   a->fd = -1;
                     45: }
                     46: 
                     47: static void
                     48: proc_cleanup(struct pci_access *a)
                     49: {
                     50:   if (a->fd >= 0)
                     51:     {
                     52:       close(a->fd);
                     53:       a->fd = -1;
                     54:     }
                     55: }
                     56: 
                     57: static void
                     58: proc_scan(struct pci_access *a)
                     59: {
                     60:   FILE *f;
                     61:   char buf[512];
                     62: 
                     63:   if (snprintf(buf, sizeof(buf), "%s/devices", pci_get_param(a, "proc.path")) == sizeof(buf))
                     64:     a->error("File name too long");
                     65:   f = fopen(buf, "r");
                     66:   if (!f)
                     67:     a->error("Cannot open %s", buf);
                     68:   while (fgets(buf, sizeof(buf)-1, f))
                     69:     {
                     70:       struct pci_dev *d = pci_alloc_dev(a);
                     71:       unsigned int dfn, vend, cnt, known;
                     72: 
                     73: #define F " " PCIADDR_T_FMT
                     74:       cnt = sscanf(buf, "%x %x %x" F F F F F F F F F F F F F F,
                     75:             &dfn,
                     76:             &vend,
                     77:             &d->irq,
                     78:             &d->base_addr[0],
                     79:             &d->base_addr[1],
                     80:             &d->base_addr[2],
                     81:             &d->base_addr[3],
                     82:             &d->base_addr[4],
                     83:             &d->base_addr[5],
                     84:             &d->rom_base_addr,
                     85:             &d->size[0],
                     86:             &d->size[1],
                     87:             &d->size[2],
                     88:             &d->size[3],
                     89:             &d->size[4],
                     90:             &d->size[5],
                     91:             &d->rom_size);
                     92: #undef F
                     93:       if (cnt != 9 && cnt != 10 && cnt != 17)
                     94:        a->error("proc: parse error (read only %d items)", cnt);
                     95:       d->bus = dfn >> 8U;
                     96:       d->dev = PCI_SLOT(dfn & 0xff);
                     97:       d->func = PCI_FUNC(dfn & 0xff);
                     98:       d->vendor_id = vend >> 16U;
                     99:       d->device_id = vend & 0xffff;
                    100:       known = 0;
                    101:       if (!a->buscentric)
                    102:        {
                    103:          known |= PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES;
                    104:          if (cnt >= 10)
                    105:            known |= PCI_FILL_ROM_BASE;
                    106:          if (cnt >= 17)
                    107:            known |= PCI_FILL_SIZES;
                    108:        }
                    109:       d->known_fields = known;
                    110:       pci_link_dev(a, d);
                    111:     }
                    112:   fclose(f);
                    113: }
                    114: 
                    115: static int
                    116: proc_setup(struct pci_dev *d, int rw)
                    117: {
                    118:   struct pci_access *a = d->access;
                    119: 
                    120:   if (a->cached_dev != d || a->fd_rw < rw)
                    121:     {
                    122:       char buf[1024];
                    123:       int e;
                    124:       if (a->fd >= 0)
                    125:        close(a->fd);
                    126:       e = snprintf(buf, sizeof(buf), "%s/%02x/%02x.%d",
                    127:                   pci_get_param(a, "proc.path"),
                    128:                   d->bus, d->dev, d->func);
                    129:       if (e < 0 || e >= (int) sizeof(buf))
                    130:        a->error("File name too long");
                    131:       a->fd_rw = a->writeable || rw;
                    132:       a->fd = open(buf, a->fd_rw ? O_RDWR : O_RDONLY);
                    133:       if (a->fd < 0)
                    134:        {
                    135:          e = snprintf(buf, sizeof(buf), "%s/%04x:%02x/%02x.%d",
                    136:                       pci_get_param(a, "proc.path"),
                    137:                       d->domain, d->bus, d->dev, d->func);
                    138:          if (e < 0 || e >= (int) sizeof(buf))
                    139:            a->error("File name too long");
                    140:          a->fd = open(buf, a->fd_rw ? O_RDWR : O_RDONLY);
                    141:        }
                    142:       if (a->fd < 0)
                    143:        a->warning("Cannot open %s", buf);
                    144:       a->cached_dev = d;
                    145:       a->fd_pos = 0;
                    146:     }
                    147:   return a->fd;
                    148: }
                    149: 
                    150: static int
                    151: proc_read(struct pci_dev *d, int pos, byte *buf, int len)
                    152: {
                    153:   int fd = proc_setup(d, 0);
                    154:   int res;
                    155: 
                    156:   if (fd < 0)
                    157:     return 0;
                    158:   res = do_read(d, fd, buf, len, pos);
                    159:   if (res < 0)
                    160:     {
                    161:       d->access->warning("proc_read: read failed: %s", strerror(errno));
                    162:       return 0;
                    163:     }
                    164:   else if (res != len)
                    165:     return 0;
                    166:   return 1;
                    167: }
                    168: 
                    169: static int
                    170: proc_write(struct pci_dev *d, int pos, byte *buf, int len)
                    171: {
                    172:   int fd = proc_setup(d, 1);
                    173:   int res;
                    174: 
                    175:   if (fd < 0)
                    176:     return 0;
                    177:   res = do_write(d, fd, buf, len, pos);
                    178:   if (res < 0)
                    179:     {
                    180:       d->access->warning("proc_write: write failed: %s", strerror(errno));
                    181:       return 0;
                    182:     }
                    183:   else if (res != len)
                    184:     {
                    185:       d->access->warning("proc_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res);
                    186:       return 0;
                    187:     }
                    188:   return 1;
                    189: }
                    190: 
                    191: static void
                    192: proc_cleanup_dev(struct pci_dev *d)
                    193: {
                    194:   if (d->access->cached_dev == d)
                    195:     d->access->cached_dev = NULL;
                    196: }
                    197: 
                    198: struct pci_methods pm_linux_proc = {
                    199:   "linux-proc",
                    200:   "The proc file system on Linux",
                    201:   proc_config,
                    202:   proc_detect,
                    203:   proc_init,
                    204:   proc_cleanup,
                    205:   proc_scan,
                    206:   pci_generic_fill_info,
                    207:   proc_read,
                    208:   proc_write,
                    209:   NULL,                                        /* read_vpd */
                    210:   NULL,                                        /* init_dev */
                    211:   proc_cleanup_dev
                    212: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>