2 * The PCI Library -- AIX /dev/pci[0-n] access
4 * Copyright (c) 1999 Jari Kirma <kirma@cs.hut.fi>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 * Read functionality of this driver is briefly tested, and seems
11 * to supply basic information correctly, but I promise no more.
20 #include <sys/types.h>
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 }'"
31 /* AIX PCI bus device information */
33 typedef struct aix_pci_bus {
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;
44 /* Utility Routines */
47 aix_find_bus(struct pci_access *a, int bus_number)
51 for (i = 0; i < pci_bus_count; i++)
53 if (pci_buses[i].bus_number == bus_number)
59 a->error("aix_find_bus: bus number %d not found", bus_number);
63 aix_bus_open(struct pci_access *a, int bus_number)
65 aix_pci_bus *bp = aix_find_bus(a, bus_number);
70 int mode = a->writeable ? O_RDWR : O_RDONLY;
72 snprintf(devbuf, sizeof (devbuf), "/dev/%s", bp->bus_name);
73 bp->bus_fd = open(devbuf, mode, 0);
76 a->error("aix_open_bus: %s open failed", devbuf);
84 aix_bus_number(char *name)
93 snprintf(command, sizeof (command), AIX_ODMGET_CMD, name);
94 odmget_pipe = popen(command, "r");
95 if (odmget_pipe == NULL)
101 if (fgets(buf, sizeof (buf) - 1, odmget_pipe) != NULL)
103 bp = buf + 1; /* skip leading double quote */
104 bus_number = strtol(bp, &ep, 0);
113 /* first PCI bus_number is not recorded in ODM CuAt; default to 0 */
117 (void) pclose(odmget_pipe);
126 aix_config(struct pci_access *a)
128 a->method_params[PCI_ACCESS_AIX_DEVICE] = NULL;
132 aix_detect(struct pci_access *a)
135 int mode = a->writeable ? W_OK : R_OK;
136 char *command = AIX_LSDEV_CMD;
141 lsdev_pipe = popen(command, "r");
142 if (lsdev_pipe == NULL)
144 a->error("aix_config: popen(\"%s\") failed", command);
147 while (fgets(buf, sizeof (buf) - 1, lsdev_pipe) != NULL)
150 while (buf[len-1] == '\n' || buf[len-1] == '\r')
152 buf[len] = '\0'; /* clobber the newline */
154 name = (char *) pci_malloc(a, len + 1);
156 pci_buses[pci_bus_count].bus_name = name;
157 pci_buses[pci_bus_count].bus_number = 0;
158 pci_buses[pci_bus_count].bus_fd = -1;
160 a->debug("...using %s", name);
162 a->debug(", %s", name);
164 if (pci_bus_count >= PCI_BUS_MAX)
168 (void) pclose(lsdev_pipe);
170 return pci_bus_count;
174 aix_init(struct pci_access *a)
179 for (i = 0; i < pci_bus_count; i++)
181 name = pci_buses[i].bus_name;
182 pci_buses[i].bus_number = aix_bus_number(name);
187 aix_cleanup(struct pci_access *a)
191 while (pci_bus_count-- > 0)
193 bp = &pci_buses[pci_bus_count];
194 (void) free(bp->bus_name);
197 (void) close(bp->bus_fd);
204 aix_scan(struct pci_access *a)
210 bzero(busmap, sizeof(busmap));
211 for (i = 0; i < pci_bus_count; i++)
213 bus_number = pci_buses[i].bus_number;
214 if (!busmap[bus_number])
216 pci_generic_scan_bus(a, busmap, bus_number);
222 aix_read(struct pci_dev *d, int pos, byte *buf, int len)
225 int fd = aix_bus_open(d->access, d->bus);
227 mdio.md_addr = (ulong) pos;
229 mdio.md_incr = MV_BYTE;
230 mdio.md_data = (char *) buf;
231 mdio.md_sla = PCI_DEVFN(d->dev, d->func);
233 if (ioctl(fd, MIOPCFGET, &mdio) < 0)
234 d->access->error("aix_read: ioctl(MIOPCFGET) failed");
240 aix_write(struct pci_dev *d, int pos, byte *buf, int len)
243 int fd = aix_bus_open(d->access, d->bus);
245 mdio.md_addr = (ulong) pos;
247 mdio.md_incr = MV_BYTE;
248 mdio.md_data = (char *) buf;
249 mdio.md_sla = PCI_DEVFN(d->dev, d->func);
251 if (ioctl(fd, MIOPCFPUT, &mdio) < 0)
253 d->access->error("aix_write: ioctl(MIOPCFPUT) failed");
259 struct pci_methods pm_aix_device = {
266 pci_generic_fill_info,
270 NULL /* dev_cleanup */