Annotation of embedaddon/pciutils/lib/aix-device.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     The PCI Library -- AIX /dev/pci[0-n] access
        !             3:  *
        !             4:  *     Copyright (c) 1999 Jari Kirma <kirma@cs.hut.fi>
        !             5:  *
        !             6:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  *      Read functionality of this driver is briefly tested, and seems
        !            11:  *      to supply basic information correctly, but I promise no more.
        !            12:  */
        !            13: 
        !            14: #include <stdio.h>
        !            15: #include <stdlib.h>
        !            16: #include <string.h>
        !            17: #include <unistd.h>
        !            18: #include <fcntl.h>
        !            19: 
        !            20: #include <sys/types.h>
        !            21: #include <sys/mdio.h>
        !            22: 
        !            23: #include "internal.h"
        !            24: 
        !            25: #define AIX_LSDEV_CMD "/usr/sbin/lsdev -C -c bus -t pci\\* -S available -F name"
        !            26: #define AIX_ODMGET_CMD \
        !            27:   "/usr/bin/odmget -q 'name=%s and attribute=bus_number' CuAt | \
        !            28:    /usr/bin/awk '$1 == \"value\" { print $3 }'"
        !            29: 
        !            30: 
        !            31: /* AIX PCI bus device information */
        !            32: 
        !            33: typedef struct aix_pci_bus {
        !            34:     char *bus_name;
        !            35:     int   bus_number;
        !            36:     int   bus_fd;
        !            37: } aix_pci_bus;
        !            38: 
        !            39: #define PCI_BUS_MAX 16         /* arbitrary choice */
        !            40: static aix_pci_bus pci_buses[PCI_BUS_MAX];
        !            41: static int pci_bus_count = 0;
        !            42: 
        !            43: 
        !            44: /* Utility Routines */
        !            45: 
        !            46: static aix_pci_bus *
        !            47: aix_find_bus(struct pci_access *a, int bus_number)
        !            48: {
        !            49:   int i;
        !            50: 
        !            51:   for (i = 0; i < pci_bus_count; i++)
        !            52:     {
        !            53:       if (pci_buses[i].bus_number == bus_number)
        !            54:         {
        !            55:           return &pci_buses[i];
        !            56:         }
        !            57:     }
        !            58: 
        !            59:   a->error("aix_find_bus: bus number %d not found", bus_number);
        !            60: }
        !            61: 
        !            62: static int
        !            63: aix_bus_open(struct pci_access *a, int bus_number)
        !            64: {
        !            65:   aix_pci_bus *bp = aix_find_bus(a, bus_number);
        !            66: 
        !            67:   if (bp->bus_fd < 0)
        !            68:     {
        !            69:       char devbuf[256];
        !            70:       int mode = a->writeable ? O_RDWR : O_RDONLY;
        !            71: 
        !            72:       snprintf(devbuf, sizeof (devbuf), "/dev/%s", bp->bus_name);
        !            73:       bp->bus_fd = open(devbuf, mode, 0);
        !            74:       if (bp->bus_fd < 0)
        !            75:         {
        !            76:           a->error("aix_open_bus: %s open failed", devbuf);
        !            77:         }
        !            78:     }
        !            79: 
        !            80:   return bp->bus_fd;
        !            81: }
        !            82: 
        !            83: static int
        !            84: aix_bus_number(char *name)
        !            85: {
        !            86:   int bus_number;
        !            87:   FILE *odmget_pipe;
        !            88:   char command[256];
        !            89:   char buf[256];
        !            90:   char *bp;
        !            91:   char *ep;
        !            92: 
        !            93:   snprintf(command, sizeof (command), AIX_ODMGET_CMD, name);
        !            94:   odmget_pipe = popen(command, "r");
        !            95:   if (odmget_pipe == NULL)
        !            96:     {
        !            97:       /* popen failed */
        !            98:       return -1;
        !            99:     }
        !           100: 
        !           101:   if (fgets(buf, sizeof (buf) - 1, odmget_pipe) != NULL)
        !           102:     {
        !           103:       bp = buf + 1;    /* skip leading double quote */
        !           104:       bus_number = strtol(bp, &ep, 0);
        !           105:       if (bp == ep)
        !           106:         {
        !           107:           /* strtol failed */
        !           108:           bus_number = -1;
        !           109:         }
        !           110:     }
        !           111:   else
        !           112:     {
        !           113:       /* first PCI bus_number is not recorded in ODM CuAt; default to 0 */
        !           114:       bus_number = 0;
        !           115:     }
        !           116: 
        !           117:   (void) pclose(odmget_pipe);
        !           118: 
        !           119:   return bus_number;
        !           120: }
        !           121: 
        !           122: 
        !           123: /* Method entries */
        !           124: 
        !           125: static int
        !           126: aix_detect(struct pci_access *a)
        !           127: {
        !           128:   int len;
        !           129:   int mode = a->writeable ? W_OK : R_OK;
        !           130:   char *command = AIX_LSDEV_CMD;
        !           131:   FILE *lsdev_pipe;
        !           132:   char buf[256];
        !           133:   char *name;
        !           134: 
        !           135:   lsdev_pipe = popen(command, "r");
        !           136:   if (lsdev_pipe == NULL)
        !           137:     {
        !           138:       a->error("aix_config: popen(\"%s\") failed", command);
        !           139:     }
        !           140: 
        !           141:   while (fgets(buf, sizeof (buf) - 1, lsdev_pipe) != NULL)
        !           142:     {
        !           143:       len = strlen(buf);
        !           144:       while (buf[len-1] == '\n' || buf[len-1] == '\r')
        !           145:           len--;
        !           146:       buf[len] = '\0';                         /* clobber the newline */
        !           147: 
        !           148:       name = (char *) pci_malloc(a, len + 1);
        !           149:       strcpy(name, buf);
        !           150:       pci_buses[pci_bus_count].bus_name = name;
        !           151:       pci_buses[pci_bus_count].bus_number = 0;
        !           152:       pci_buses[pci_bus_count].bus_fd = -1;
        !           153:       if (!pci_bus_count)
        !           154:           a->debug("...using %s", name);
        !           155:       else
        !           156:           a->debug(", %s", name);
        !           157:       pci_bus_count++;
        !           158:       if (pci_bus_count >= PCI_BUS_MAX)
        !           159:           break;
        !           160:     }
        !           161: 
        !           162:   (void) pclose(lsdev_pipe);
        !           163: 
        !           164:   return pci_bus_count;
        !           165: }
        !           166: 
        !           167: static void
        !           168: aix_init(struct pci_access *a)
        !           169: {
        !           170:   char *name;
        !           171:   int i;
        !           172: 
        !           173:   for (i = 0; i < pci_bus_count; i++)
        !           174:     {
        !           175:       name = pci_buses[i].bus_name;
        !           176:       pci_buses[i].bus_number = aix_bus_number(name);
        !           177:     }
        !           178: }
        !           179: 
        !           180: static void
        !           181: aix_cleanup(struct pci_access *a)
        !           182: {
        !           183:   aix_pci_bus *bp;
        !           184: 
        !           185:   while (pci_bus_count-- > 0)
        !           186:     {
        !           187:       bp = &pci_buses[pci_bus_count];
        !           188:       (void) free(bp->bus_name);
        !           189:       if (bp->bus_fd >= 0)
        !           190:         {
        !           191:           (void) close(bp->bus_fd);
        !           192:           bp->bus_fd = -1;
        !           193:         }
        !           194:     }
        !           195: }
        !           196: 
        !           197: void
        !           198: aix_scan(struct pci_access *a)
        !           199: {
        !           200:   int i;
        !           201:   int bus_number;
        !           202:   byte busmap[256];
        !           203: 
        !           204:   memset(busmap, 0, sizeof(busmap));
        !           205:   for (i = 0; i < pci_bus_count; i++)
        !           206:     {
        !           207:       bus_number = pci_buses[i].bus_number;
        !           208:       if (!busmap[bus_number])
        !           209:         {
        !           210:           pci_generic_scan_bus(a, busmap, bus_number);
        !           211:         }
        !           212:     }
        !           213: }
        !           214: 
        !           215: static int
        !           216: aix_read(struct pci_dev *d, int pos, byte *buf, int len)
        !           217: {
        !           218:   struct mdio mdio;
        !           219:   int fd;
        !           220: 
        !           221:   if (pos + len > 256)
        !           222:     return 0;
        !           223: 
        !           224:   fd = aix_bus_open(d->access, d->bus);
        !           225:   mdio.md_addr = (ulong) pos;
        !           226:   mdio.md_size = len;
        !           227:   mdio.md_incr = MV_BYTE;
        !           228:   mdio.md_data = (char *) buf;
        !           229:   mdio.md_sla = PCI_DEVFN(d->dev, d->func);
        !           230: 
        !           231:   if (ioctl(fd, MIOPCFGET, &mdio) < 0)
        !           232:     d->access->error("aix_read: ioctl(MIOPCFGET) failed");
        !           233: 
        !           234:   return 1;
        !           235: }
        !           236: 
        !           237: static int
        !           238: aix_write(struct pci_dev *d, int pos, byte *buf, int len)
        !           239: {
        !           240:   struct mdio mdio;
        !           241:   int fd;
        !           242: 
        !           243:   if (pos + len > 256)
        !           244:     return 0;
        !           245: 
        !           246:   fd = aix_bus_open(d->access, d->bus);
        !           247:   mdio.md_addr = (ulong) pos;
        !           248:   mdio.md_size = len;
        !           249:   mdio.md_incr = MV_BYTE;
        !           250:   mdio.md_data = (char *) buf;
        !           251:   mdio.md_sla = PCI_DEVFN(d->dev, d->func);
        !           252: 
        !           253:   if (ioctl(fd, MIOPCFPUT, &mdio) < 0)
        !           254:     {
        !           255:       d->access->error("aix_write: ioctl(MIOPCFPUT) failed");
        !           256:     }
        !           257: 
        !           258:   return 1;
        !           259: }
        !           260: 
        !           261: struct pci_methods pm_aix_device = {
        !           262:   "aix-device",
        !           263:   "AIX /dev/pci[0-n]",
        !           264:   NULL,
        !           265:   aix_detect,
        !           266:   aix_init,
        !           267:   aix_cleanup,
        !           268:   aix_scan,
        !           269:   pci_generic_fill_info,
        !           270:   aix_read,
        !           271:   aix_write,
        !           272:   NULL,                                 /* read_vpd */
        !           273:   NULL,                                 /* dev_init */
        !           274:   NULL                                  /* dev_cleanup */
        !           275: };

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