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_detect(struct pci_access
*a
)
129 int mode
= a
->writeable
? W_OK
: R_OK
;
130 char *command
= AIX_LSDEV_CMD
;
135 lsdev_pipe
= popen(command
, "r");
136 if (lsdev_pipe
== NULL
)
138 a
->error("aix_config: popen(\"%s\") failed", command
);
141 while (fgets(buf
, sizeof (buf
) - 1, lsdev_pipe
) != NULL
)
144 while (buf
[len
-1] == '\n' || buf
[len
-1] == '\r')
146 buf
[len
] = '\0'; /* clobber the newline */
148 name
= (char *) pci_malloc(a
, len
+ 1);
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;
154 a
->debug("...using %s", name
);
156 a
->debug(", %s", name
);
158 if (pci_bus_count
>= PCI_BUS_MAX
)
162 (void) pclose(lsdev_pipe
);
164 return pci_bus_count
;
168 aix_init(struct pci_access
*a
)
173 for (i
= 0; i
< pci_bus_count
; i
++)
175 name
= pci_buses
[i
].bus_name
;
176 pci_buses
[i
].bus_number
= aix_bus_number(name
);
181 aix_cleanup(struct pci_access
*a
)
185 while (pci_bus_count
-- > 0)
187 bp
= &pci_buses
[pci_bus_count
];
188 (void) free(bp
->bus_name
);
191 (void) close(bp
->bus_fd
);
198 aix_scan(struct pci_access
*a
)
204 memset(busmap
, 0, sizeof(busmap
));
205 for (i
= 0; i
< pci_bus_count
; i
++)
207 bus_number
= pci_buses
[i
].bus_number
;
208 if (!busmap
[bus_number
])
210 pci_generic_scan_bus(a
, busmap
, bus_number
);
216 aix_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
224 fd
= aix_bus_open(d
->access
, d
->bus
);
225 mdio
.md_addr
= (ulong
) pos
;
227 mdio
.md_incr
= MV_BYTE
;
228 mdio
.md_data
= (char *) buf
;
229 mdio
.md_sla
= PCI_DEVFN(d
->dev
, d
->func
);
231 if (ioctl(fd
, MIOPCFGET
, &mdio
) < 0)
232 d
->access
->error("aix_read: ioctl(MIOPCFGET) failed");
238 aix_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
246 fd
= aix_bus_open(d
->access
, d
->bus
);
247 mdio
.md_addr
= (ulong
) pos
;
249 mdio
.md_incr
= MV_BYTE
;
250 mdio
.md_data
= (char *) buf
;
251 mdio
.md_sla
= PCI_DEVFN(d
->dev
, d
->func
);
253 if (ioctl(fd
, MIOPCFPUT
, &mdio
) < 0)
255 d
->access
->error("aix_write: ioctl(MIOPCFPUT) failed");
261 struct pci_methods pm_aix_device
= {
269 pci_generic_fill_info
,
274 NULL
/* dev_cleanup */