OSDN Git Service

Clean up formatting of solx_devfs.c
[android-x86/external-libpciaccess.git] / src / solx_devfs.c
1 /*
2  * (C) Copyright IBM Corporation 2006
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
26  *
27  * Permission is hereby granted, free of charge, to any person obtaining a
28  * copy of this software and associated documentation files (the
29  * "Software"), to deal in the Software without restriction, including
30  * without limitation the rights to use, copy, modify, merge, publish,
31  * distribute, and/or sell copies of the Software, and to permit persons
32  * to whom the Software is furnished to do so, provided that the above
33  * copyright notice(s) and this permission notice appear in all copies of
34  * the Software and that both the above copyright notice(s) and this
35  * permission notice appear in supporting documentation.
36  *
37  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
40  * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
41  * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
42  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
43  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
44  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
45  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46  *
47  * Except as contained in this notice, the name of a copyright holder
48  * shall not be used in advertising or otherwise to promote the sale, use
49  * or other dealings in this Software without prior written authorization
50  * of the copyright holder.
51  */
52 /*
53  * Solaris devfs interfaces
54  */
55
56 #include <stdlib.h>
57 #include <strings.h>
58 #include <stdio.h>
59 #include <unistd.h>
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <fcntl.h>
63 #include <sys/mman.h>
64 #include <dirent.h>
65 #include <errno.h>
66 #include <sys/pci.h>
67 #include <assert.h>
68 #include <libdevinfo.h>
69 #include "pci_tools.h"
70
71 #include "pciaccess.h"
72 #include "pciaccess_private.h"
73
74 #define MAX_DEVICES     256
75 #define CELL_NUMS_1275          (sizeof(pci_regspec_t)/sizeof(uint_t))
76
77 typedef union {
78     uint8_t bytes[16 * sizeof (uint32_t)];
79     uint32_t dwords[16];
80 } pci_conf_hdr_t;
81
82 typedef struct i_devnode {
83     uint8_t bus;
84     uint8_t dev;
85     uint8_t func;
86     di_node_t node;
87 } i_devnode_t;
88
89 typedef struct nexus {
90     int fd;
91     int domain;
92     struct nexus *next;
93 } nexus_t;
94
95 static nexus_t *nexus_list = NULL;
96 static int num_domains = 0;
97 static int xsvc_fd = -1;
98
99 /*
100  * Read config space in native processor endianness.  Endian-neutral
101  * processing can then take place.  On big endian machines, MSB and LSB
102  * of little endian data end up switched if read as little endian.
103  * They are in correct order if read as big endian.
104  */
105 #if defined(__sparc)
106 # define NATIVE_ENDIAN  PCITOOL_ACC_ATTR_ENDN_BIG
107 #elif defined(__x86)
108 # define NATIVE_ENDIAN  PCITOOL_ACC_ATTR_ENDN_LTL
109 #else
110 # error "ISA is neither __sparc nor __x86"
111 #endif
112
113 /*
114  * Identify problematic southbridges.  These have device id 0x5249 and
115  * vendor id 0x10b9.  Check for revision ID 0 and class code 060400 as well.
116  * Values are little endian, so they are reversed for SPARC.
117  *
118  * Check for these southbridges on all architectures, as the issue is a
119  * southbridge issue, independent of processor.
120  *
121  * If one of these is found during probing, skip probing other devs/funcs on
122  * the rest of the bus, since the southbridge and all devs underneath will
123  * otherwise disappear.
124  */
125 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG)
126 # define U45_SB_DEVID_VID       0xb9104952
127 # define U45_SB_CLASS_RID       0x00000406
128 #else
129 # define U45_SB_DEVID_VID       0x524910b9
130 # define U45_SB_CLASS_RID       0x06040000
131 #endif
132
133 #define DEBUGON 0
134
135
136 static int pci_device_solx_devfs_map_range(struct pci_device *dev,
137     struct pci_device_mapping *map);
138
139 static int pci_device_solx_devfs_read_rom( struct pci_device * dev,
140     void * buffer );
141
142 static int pci_device_solx_devfs_probe( struct pci_device * dev );
143
144 static int pci_device_solx_devfs_read( struct pci_device * dev, void * data,
145     pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_read );
146
147 static int pci_device_solx_devfs_write( struct pci_device * dev,
148     const void * data, pciaddr_t offset, pciaddr_t size,
149     pciaddr_t * bytes_written );
150
151 static int probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p,
152                      struct pci_system *pci_sys);
153
154 static int do_probe(nexus_t *nexus, struct pci_system *pci_sys);
155
156 static int probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg);
157
158 static void pci_system_solx_devfs_destroy( void );
159
160 static int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no,
161                              uint8_t func_no, pci_conf_hdr_t *config_hdr_p);
162
163 int pci_system_solx_devfs_create( void );
164
165 static const struct pci_system_methods solx_devfs_methods = {
166     .destroy = pci_system_solx_devfs_destroy,
167     .destroy_device = NULL,
168     .read_rom = pci_device_solx_devfs_read_rom,
169     .probe = pci_device_solx_devfs_probe,
170     .map_range = pci_device_solx_devfs_map_range,
171     .unmap_range = pci_device_generic_unmap_range,
172
173     .read = pci_device_solx_devfs_read,
174     .write = pci_device_solx_devfs_write,
175
176     .fill_capabilities = pci_fill_capabilities_generic
177 };
178
179 static nexus_t *
180 find_nexus_for_domain( int domain )
181 {
182     nexus_t *nexus;
183
184     for (nexus = nexus_list ; nexus != NULL ; nexus = nexus->next) {
185         if (nexus->domain == domain) {
186             return nexus;
187         }
188     }
189     return NULL;
190 }
191
192 static uint32_t
193 get_config_hdr_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset,
194                      uint8_t size)
195 {
196     uint32_t value = 0;
197
198     while (size-- > 0) {
199         value = (value << 8) + config_hdr_p->bytes[offset + size];
200     }
201
202     return value;
203 }
204
205 #define GET_CONFIG_VAL_8(offset) \
206         (config_hdr.bytes[offset])
207 #define GET_CONFIG_VAL_16(offset) \
208         (uint16_t)get_config_hdr_value(&config_hdr, offset, 2)
209 #define GET_CONFIG_VAL_32(offset) \
210         (uint32_t)get_config_hdr_value(&config_hdr, offset, 4)
211
212 /*
213  * Release all the resources
214  * Solaris version
215  */
216 static void
217 pci_system_solx_devfs_destroy( void )
218 {
219     /*
220      * the memory allocated in create routines
221      * will be freed in pci_system_init
222      * It is more reasonable to free them here
223      */
224     nexus_t *nexus, *next;
225
226     for (nexus = nexus_list ; nexus != NULL ; nexus = next) {
227         next = nexus->next;
228         close(nexus->fd);
229         free(nexus);
230     }
231     nexus_list = NULL;
232
233     if (xsvc_fd >= 0) {
234         close(xsvc_fd);
235         xsvc_fd = -1;
236     }
237 }
238
239 /*
240  * Attempt to access PCI subsystem using Solaris's devfs interface.
241  * Solaris version
242  */
243 int
244 pci_system_solx_devfs_create( void )
245 {
246     int err = 0;
247     di_node_t di_node;
248
249
250     if (nexus_list != NULL) {
251         return 0;
252     }
253
254     /*
255      * Only allow MAX_DEVICES exists
256      * I will fix it later to get
257      * the total devices first
258      */
259     if ((pci_sys = calloc(1, sizeof (struct pci_system))) != NULL) {
260         pci_sys->methods = &solx_devfs_methods;
261         if ((pci_sys->devices =
262              calloc(MAX_DEVICES, sizeof (struct pci_device_private)))
263             != NULL) {
264             if ((di_node = di_init("/", DINFOCPYALL))
265                 == DI_NODE_NIL) {
266                 err = errno;
267                 (void) fprintf(stderr, "di_init() failed: %s\n",
268                                strerror(errno));
269             } else {
270                 (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, pci_sys,
271                                      probe_nexus_node);
272                 di_fini(di_node);
273             }
274         }
275         else {
276             err = errno;
277         }
278     } else {
279         err = errno;
280     }
281
282     if (err != 0) {
283         if (pci_sys != NULL) {
284             free(pci_sys->devices);
285             free(pci_sys);
286             pci_sys = NULL;
287         }
288     }
289
290     return (err);
291 }
292
293 /*
294  * Retrieve first 16 dwords of device's config header, except for the first
295  * dword.  First 16 dwords are defined by the PCI specification.
296  */
297 static int
298 get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no,
299                   pci_conf_hdr_t *config_hdr_p)
300 {
301     pcitool_reg_t cfg_prg;
302     int i;
303     int rval = 0;
304
305     /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */
306     cfg_prg.offset = 0;
307     cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
308     cfg_prg.bus_no = bus_no;
309     cfg_prg.dev_no = dev_no;
310     cfg_prg.func_no = func_no;
311     cfg_prg.barnum = 0;
312     cfg_prg.user_version = PCITOOL_USER_VERSION;
313
314     /* Get dwords 1-15 of config space. They must be read as uint32_t. */
315     for (i = 1; i < (sizeof (pci_conf_hdr_t) / sizeof (uint32_t)); i++) {
316         cfg_prg.offset += sizeof (uint32_t);
317         if ((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) {
318             break;
319         }
320         config_hdr_p->dwords[i] = (uint32_t)cfg_prg.data;
321     }
322
323     return (rval);
324 }
325
326
327 /*
328  * Probe device's functions.  Modifies many fields in the prg_p.
329  */
330 static int
331 probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, struct pci_system *pci_sys)
332 {
333     pci_conf_hdr_t      config_hdr;
334     boolean_t           multi_function_device;
335     int8_t              func;
336     int8_t              first_func = 0;
337     int8_t              last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT;
338     int                 rval = 0;
339     struct pci_device * pci_base;
340
341     /*
342      * Loop through at least func=first_func.  Continue looping through
343      * functions if there are no errors and the device is a multi-function
344      * device.
345      *
346      * (Note, if first_func == 0, header will show whether multifunction
347      * device and set multi_function_device.  If first_func != 0, then we
348      * will force the loop as the user wants a specific function to be
349      * checked.
350      */
351     for (func = first_func, multi_function_device = B_FALSE;
352          ((func <= last_func) &&
353           ((func == first_func) || (multi_function_device)));
354          func++) {
355         prg_p->func_no = func;
356
357         /*
358          * Four things can happen here:
359          *
360          * 1) ioctl comes back as EFAULT and prg_p->status is
361          *    PCITOOL_INVALID_ADDRESS.  There is no device at this location.
362          *
363          * 2) ioctl comes back successful and the data comes back as
364          *    zero.  Config space is mapped but no device responded.
365          *
366          * 3) ioctl comes back successful and the data comes back as
367          *    non-zero.  We've found a device.
368          *
369          * 4) Some other error occurs in an ioctl.
370          */
371
372         prg_p->status = PCITOOL_SUCCESS;
373         prg_p->offset = 0;
374         prg_p->data = 0;
375         prg_p->user_version = PCITOOL_USER_VERSION;
376
377         if (((rval = ioctl(nexus->fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) ||
378             (prg_p->data == 0xffffffff)) {
379
380             /*
381              * Accept errno == EINVAL along with status of
382              * PCITOOL_OUT_OF_RANGE because some systems
383              * don't implement the full range of config space.
384              * Leave the loop quietly in this case.
385              */
386             if ((errno == EINVAL) ||
387                 (prg_p->status == PCITOOL_OUT_OF_RANGE)) {
388                 break;
389             }
390
391             /*
392              * Exit silently with ENXIO as this means that there are
393              * no devices under the pci root nexus.
394              */
395             else if ((errno == ENXIO) &&
396                      (prg_p->status == PCITOOL_IO_ERROR)) {
397                 break;
398             }
399
400             /*
401              * Expect errno == EFAULT along with status of
402              * PCITOOL_INVALID_ADDRESS because there won't be
403              * devices at each stop.  Quit on any other error.
404              */
405             else if (((errno != EFAULT) ||
406                       (prg_p->status != PCITOOL_INVALID_ADDRESS)) &&
407                      (prg_p->data != 0xffffffff)) {
408                 break;
409             }
410
411             /*
412              * If no function at this location,
413              * just advance to the next function.
414              */
415             else {
416                 rval = 0;
417             }
418
419             /*
420              * Data came back as 0.
421              * Treat as unresponsive device and check next device.
422              */
423         } else if (prg_p->data == 0) {
424             rval = 0;
425             break;      /* Func loop. */
426
427             /* Found something. */
428         } else {
429             config_hdr.dwords[0] = (uint32_t)prg_p->data;
430
431             /* Get the rest of the PCI header. */
432             if ((rval = get_config_header(nexus->fd, prg_p->bus_no,
433                                           prg_p->dev_no, prg_p->func_no,
434                                           &config_hdr)) != 0) {
435                 break;
436             }
437
438             /*
439              * Special case for the type of Southbridge found on
440              * Ultra-45 and other sun4u fire workstations.
441              */
442             if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) &&
443                 (config_hdr.dwords[2] == U45_SB_CLASS_RID)) {
444                 rval = ECANCELED;
445                 break;
446             }
447
448             /*
449              * Found one device with bus number, device number and
450              * function number.
451              */
452
453             pci_base = &pci_sys->devices[pci_sys->num_devices].base;
454
455             /*
456              * Domain is peer bus??
457              */
458             pci_base->domain = nexus->domain;
459             pci_base->bus = prg_p->bus_no;
460             pci_base->dev = prg_p->dev_no;
461             pci_base->func = func;
462
463             /*
464              * for the format of device_class, see struct pci_device;
465              */
466
467             pci_base->device_class =
468                 (GET_CONFIG_VAL_8(PCI_CONF_BASCLASS) << 16) |
469                 (GET_CONFIG_VAL_8(PCI_CONF_SUBCLASS) << 8) |
470                 GET_CONFIG_VAL_8(PCI_CONF_PROGCLASS);
471
472             pci_base->revision          = GET_CONFIG_VAL_8(PCI_CONF_REVID);
473             pci_base->vendor_id         = GET_CONFIG_VAL_16(PCI_CONF_VENID);
474             pci_base->device_id         = GET_CONFIG_VAL_16(PCI_CONF_DEVID);
475             pci_base->subvendor_id      = GET_CONFIG_VAL_16(PCI_CONF_SUBVENID);
476             pci_base->subdevice_id      = GET_CONFIG_VAL_16(PCI_CONF_SUBSYSID);
477
478             pci_sys->devices[pci_sys->num_devices].header_type
479                                         = GET_CONFIG_VAL_8(PCI_CONF_HEADER);
480
481 #if DEBUGON
482             fprintf(stderr, "busno = %x, devno = %x, funcno = %x\n",
483                     prg_p->bus_no, prg_p->dev_no, func);
484 #endif
485
486             pci_sys->num_devices++;
487
488             /*
489              * Accommodate devices which state their
490              * multi-functionality only in their function 0 config
491              * space.  Note multi-functionality throughout probing
492              * of all of this device's functions.
493              */
494             if (config_hdr.bytes[PCI_CONF_HEADER] & PCI_HEADER_MULTI) {
495                 multi_function_device = B_TRUE;
496             }
497         }
498     }
499
500     return (rval);
501 }
502
503 /*
504  * This function is called from di_walk_minor() when any PROBE is processed
505  */
506 static int
507 probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
508 {
509     struct pci_system *pci_sys = (struct pci_system *) arg;
510     char *nexus_name;
511     nexus_t *nexus;
512     int fd;
513     char nexus_path[MAXPATHLEN];
514
515     nexus = calloc(1, sizeof(nexus_t));
516     if (nexus == NULL) {
517         (void) fprintf(stderr, "Error allocating memory for nexus: %s\n",
518                        strerror(errno));
519         return DI_WALK_TERMINATE;
520     }
521
522     nexus_name = di_devfs_minor_path(minor);
523     if (nexus_name == NULL) {
524         (void) fprintf(stderr, "Error getting nexus path: %s\n",
525                        strerror(errno));
526         free(nexus);
527         return (DI_WALK_CONTINUE);
528     }
529
530     snprintf(nexus_path, sizeof(nexus_path), "/devices%s", nexus_name);
531
532     if ((fd = open(nexus_path, O_RDWR)) >= 0) {
533         nexus->fd = fd;
534         nexus->domain = num_domains++;
535         if ((do_probe(nexus, pci_sys) != 0) && (errno != ENXIO)) {
536             (void) fprintf(stderr, "Error probing node %s: %s\n",
537                            nexus_path, strerror(errno));
538             (void) close(fd);
539             free(nexus);
540         } else {
541             nexus->next = nexus_list;
542             nexus_list = nexus;
543         }
544     } else {
545         (void) fprintf(stderr, "Error opening %s: %s\n",
546                        nexus_path, strerror(errno));
547         free(nexus);
548     }
549     di_devfs_path_free(nexus_name);
550
551     return DI_WALK_CONTINUE;
552 }
553
554
555 /*
556  * Solaris version
557  * Probe a given nexus config space for devices.
558  *
559  * fd is the file descriptor of the nexus.
560  * input_args contains commandline options as specified by the user.
561  */
562 static int
563 do_probe(nexus_t *nexus, struct pci_system *pci_sys)
564 {
565     pcitool_reg_t prg;
566     uint32_t bus;
567     uint8_t dev;
568     uint32_t last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT;
569     uint8_t last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT;
570     uint8_t first_bus = 0;
571     uint8_t first_dev = 0;
572     int rval = 0;
573
574     prg.barnum = 0;     /* Config space. */
575
576     /* Must read in 4-byte quantities. */
577     prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
578
579     prg.data = 0;
580
581     /*
582      * Loop through all valid bus / dev / func combinations to check for
583      * all devices, with the following exceptions:
584      *
585      * When nothing is found at function 0 of a bus / dev combination, skip
586      * the other functions of that bus / dev combination.
587      *
588      * When a found device's function 0 is probed and it is determined that
589      * it is not a multifunction device, skip probing of that device's
590      * other functions.
591      */
592     for (bus = first_bus; ((bus <= last_bus) && (rval == 0)); bus++) {
593         prg.bus_no = (uint8_t)bus;
594
595         for (dev = first_dev; ((dev <= last_dev) && (rval == 0)); dev++) {
596             prg.dev_no = dev;
597             rval = probe_dev(nexus, &prg, pci_sys);
598         }
599
600         /*
601          * Ultra-45 southbridge workaround:
602          * ECANCELED tells to skip to the next bus.
603          */
604         if (rval == ECANCELED) {
605             rval = 0;
606         }
607     }
608     if (pci_sys->num_devices > MAX_DEVICES) {
609         (void) fprintf(stderr, "pci devices reach maximum number\n");
610     }
611
612     return (rval);
613 }
614
615 static int
616 find_target_node(di_node_t node, void *arg)
617 {
618     int *regbuf = NULL;
619     int len = 0;
620     uint32_t busno, funcno, devno;
621     i_devnode_t *devnode;
622     void *prop = DI_PROP_NIL;
623     int i;
624
625     devnode = (i_devnode_t *)arg;
626
627     /*
628      * Test the property functions, only for testing
629      */
630     /*
631     (void) fprintf(stderr, "start of node 0x%x\n", node->nodeid);
632     while ((prop = di_prop_hw_next(node, prop)) != DI_PROP_NIL) {
633         (void) fprintf(stderr, "name=%s: ", di_prop_name(prop));
634         len = 0;
635         if (!strcmp(di_prop_name(prop), "reg")) {
636             len = di_prop_ints(prop, &regbuf);
637         }
638         for (i = 0; i < len; i++) {
639             fprintf(stderr, "0x%0x.", regbuf[i]);
640         }
641         fprintf(stderr, "\n");
642     }
643     (void) fprintf(stderr, "end of node 0x%x\n", node->nodeid);
644     */
645
646     len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &regbuf);
647
648     if (len <= 0) {
649 #if DEBUGON
650         fprintf(stderr, "error = %x\n", errno);
651         fprintf(stderr, "can not find assigned-address\n");
652 #endif
653         return (DI_WALK_CONTINUE);
654     }
655
656     busno = PCI_REG_BUS_G(regbuf[0]);
657     devno = PCI_REG_DEV_G(regbuf[0]);
658     funcno = PCI_REG_FUNC_G(regbuf[0]);
659
660     if ((busno == devnode->bus) &&
661         (devno == devnode->dev) &&
662         (funcno == devnode->func)) {
663         devnode->node = node;
664
665         return (DI_WALK_TERMINATE);
666     }
667
668     return (DI_WALK_CONTINUE);
669 }
670
671 /*
672  * Solaris version
673  */
674 static int
675 pci_device_solx_devfs_probe( struct pci_device * dev )
676 {
677     uint8_t  config[256];
678     int err;
679     di_node_t rnode;
680     i_devnode_t args;
681     int *regbuf;
682     pci_regspec_t *reg;
683     int i;
684     pciaddr_t bytes;
685     int len = 0;
686
687     err = pci_device_solx_devfs_read( dev, config, 0, 256, & bytes );
688     args.node = DI_NODE_NIL;
689
690     if ( bytes >= 64 ) {
691         struct pci_device_private *priv =
692             (struct pci_device_private *) dev;
693
694         dev->vendor_id = (uint16_t)config[0] + ((uint16_t)config[1] << 8);
695         dev->device_id = (uint16_t)config[2] + ((uint16_t)config[3] << 8);
696         dev->device_class = (uint32_t)config[9] +
697             ((uint32_t)config[10] << 8) +
698             ((uint16_t)config[11] << 16);
699
700         /*
701          * device class code is already there.
702          * see probe_dev function.
703          */
704         dev->revision = config[8];
705         dev->subvendor_id = (uint16_t)config[44] + ((uint16_t)config[45] << 8);
706         dev->subdevice_id = (uint16_t)config[46] + ((uint16_t)config[47] << 8);
707         dev->irq = config[60];
708
709         priv->header_type = config[14];
710         /*
711          * starting to find if it is MEM/MEM64/IO
712          * using libdevinfo
713          */
714         if ((rnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
715             (void) fprintf(stderr, "di_init failed: %s\n", strerror(errno));
716             err = errno;
717         } else {
718             args.bus = dev->bus;
719             args.dev = dev->dev;
720             args.func = dev->func;
721             (void) di_walk_node(rnode, DI_WALK_CLDFIRST,
722                                 (void *)&args, find_target_node);
723             di_fini(rnode);
724         }
725     }
726     if (args.node != DI_NODE_NIL) {
727         /*
728          * It will success for sure, because it was
729          * successfully called in find_target_node
730          */
731         len = di_prop_lookup_ints(DDI_DEV_T_ANY, args.node,
732                                   "assigned-addresses",
733                                   &regbuf);
734
735     }
736
737     if (len <= 0)
738         return (err);
739
740
741     /*
742      * how to find the size of rom???
743      * if the device has expansion rom,
744      * it must be listed in the last
745      * cells because solaris find probe
746      * the base address from offset 0x10
747      * to 0x30h. So only check the last
748      * item.
749      */
750     reg = (pci_regspec_t *)&regbuf[len - CELL_NUMS_1275];
751     if (PCI_REG_REG_G(reg->pci_phys_hi) == PCI_CONF_ROM) {
752         /*
753          * rom can only be 32 bits
754          */
755         dev->rom_size = reg->pci_size_low;
756         len = len - CELL_NUMS_1275;
757     }
758     else {
759         /*
760          * size default to 64K and base address
761          * default to 0xC0000
762          */
763         dev->rom_size = 0x10000;
764     }
765
766     /*
767      * solaris has its own BAR index. To be sure that
768      * Xorg has the same BAR number as solaris. ????
769      */
770     for (i = 0; i < len; i = i + CELL_NUMS_1275) {
771         int ent = i/CELL_NUMS_1275;
772
773         reg = (pci_regspec_t *)&regbuf[i];
774
775         /*
776          * non relocatable resource is excluded
777          * such like 0xa0000, 0x3b0. If it is met,
778          * the loop is broken;
779          */
780         if (!PCI_REG_REG_G(reg->pci_phys_hi))
781             break;
782
783         if (reg->pci_phys_hi & PCI_PREFETCH_B) {
784             dev->regions[ent].is_prefetchable = 1;
785         }
786
787         switch (reg->pci_phys_hi & PCI_REG_ADDR_M) {
788             case PCI_ADDR_IO:
789                 dev->regions[ent].is_IO = 1;
790                 break;
791             case PCI_ADDR_MEM32:
792                 break;
793             case PCI_ADDR_MEM64:
794                 dev->regions[ent].is_64 = 1;
795                 break;
796         }
797
798         /*
799          * We split the shift count 32 into two 16 to
800          * avoid the complaining of the compiler
801          */
802         dev->regions[ent].base_addr = reg->pci_phys_low +
803             ((reg->pci_phys_mid << 16) << 16);
804         dev->regions[ent].size = reg->pci_size_low +
805             ((reg->pci_size_hi << 16) << 16);
806     }
807
808     return (err);
809 }
810
811 /*
812  * Solaris version: read the ROM data
813  */
814 static int
815 pci_device_solx_devfs_read_rom( struct pci_device * dev, void * buffer )
816 {
817     void *prom = MAP_FAILED;
818
819     if (xsvc_fd < 0) {
820         if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) {
821             (void) fprintf(stderr, "can not open xsvc driver\n");
822
823             return (-1);
824         }
825     }
826
827     prom = mmap(NULL, dev->rom_size,
828                 PROT_READ, MAP_SHARED,
829                 xsvc_fd, 0xC0000);
830
831     if (prom == MAP_FAILED) {
832         (void) fprintf(stderr, "map rom base =0xC0000 failed");
833         return (-1);
834     }
835     (void) bcopy(prom, buffer, dev->rom_size);
836
837     /*
838      * Still used xsvc to do the user space mapping
839      */
840     return (0);
841 }
842
843 /*
844  * solaris version: Read the configurations space of the devices
845  */
846 static int
847 pci_device_solx_devfs_read( struct pci_device * dev, void * data,
848                              pciaddr_t offset, pciaddr_t size,
849                              pciaddr_t * bytes_read )
850 {
851     pcitool_reg_t cfg_prg;
852     int err = 0;
853     int i = 0;
854     nexus_t *nexus = find_nexus_for_domain(dev->domain);
855
856     *bytes_read = 0;
857
858     if ( nexus == NULL ) {
859         return ENODEV;
860     }
861
862     cfg_prg.offset = offset;
863     cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN;
864     cfg_prg.bus_no = dev->bus;
865     cfg_prg.dev_no = dev->dev;
866     cfg_prg.func_no = dev->func;
867     cfg_prg.barnum = 0;
868     cfg_prg.user_version = PCITOOL_USER_VERSION;
869
870     for (i = 0; i < size; i += PCITOOL_ACC_ATTR_SIZE(PCITOOL_ACC_ATTR_SIZE_1))
871     {
872         cfg_prg.offset = offset + i;
873
874         if ((err = ioctl(nexus->fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) {
875             fprintf(stderr, "read bdf<%x,%x,%x,%llx> config space failure\n",
876                     cfg_prg.bus_no,
877                     cfg_prg.dev_no,
878                     cfg_prg.func_no,
879                     cfg_prg.offset);
880             fprintf(stderr, "Failure cause = %x\n", err);
881             break;
882         }
883
884         ((uint8_t *)data)[i] = (uint8_t)cfg_prg.data;
885         /*
886          * DWORDS Offset or bytes Offset ??
887          */
888     }
889     *bytes_read = i;
890
891     return (err);
892 }
893
894 /*
895  * Solaris version
896  */
897 static int
898 pci_device_solx_devfs_write( struct pci_device * dev, const void * data,
899                              pciaddr_t offset, pciaddr_t size,
900                              pciaddr_t * bytes_written )
901 {
902     pcitool_reg_t cfg_prg;
903     int err = 0;
904     int cmd;
905     nexus_t *nexus = find_nexus_for_domain(dev->domain);
906
907     if ( bytes_written != NULL ) {
908         *bytes_written = 0;
909     }
910
911     if ( nexus == NULL ) {
912         return ENODEV;
913     }
914
915     cfg_prg.offset = offset;
916     switch (size) {
917         case 1:
918             cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN;
919             break;
920         case 2:
921             cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_2 + NATIVE_ENDIAN;
922             break;
923         case 4:
924             cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
925             break;
926         case 8:
927             cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_8 + NATIVE_ENDIAN;
928             break;
929         default:
930             assert(0);
931     }
932     cfg_prg.bus_no = dev->bus;
933     cfg_prg.dev_no = dev->dev;
934     cfg_prg.func_no = dev->func;
935     cfg_prg.barnum = 0;
936     cfg_prg.user_version = PCITOOL_USER_VERSION;
937     cfg_prg.data = *((uint64_t *)data);
938
939     /*
940      * Check if this device is bridge device.
941      * If it is, it is also a nexus node???
942      * It seems that there is no explicit
943      * PCI nexus device for X86, so not applicable
944      * from pcitool_bus_reg_ops in pci_tools.c
945      */
946     cmd = PCITOOL_DEVICE_SET_REG;
947
948     if ((err = ioctl(nexus->fd, cmd, &cfg_prg)) != 0) {
949         return (err);
950     }
951     *bytes_written = size;
952
953     return (err);
954 }
955
956
957 /**
958  * Map a memory region for a device using /dev/xsvc.
959  *
960  * \param dev   Device whose memory region is to be mapped.
961  * \param map   Parameters of the mapping that is to be created.
962  *
963  * \return
964  * Zero on success or an \c errno value on failure.
965  */
966 static int
967 pci_device_solx_devfs_map_range(struct pci_device *dev,
968                                 struct pci_device_mapping *map)
969 {
970     const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
971                         ? (PROT_READ | PROT_WRITE) : PROT_READ;
972     int err = 0;
973
974     if (xsvc_fd < 0) {
975         if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) {
976             (void) fprintf(stderr, "can not open xsvc driver\n");
977             return errno;
978         }
979     }
980
981     map->memory = mmap(NULL, map->size, prot, MAP_SHARED, xsvc_fd, map->base);
982     if (map->memory == MAP_FAILED) {
983         err = errno;
984
985         (void) fprintf(stderr, "map rom region =%llx failed", map->base);
986     }
987
988     return err;
989 }