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>