Annotation of embedaddon/pciutils/lib/proc.c, revision 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>