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