4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
27 #include <sys/sunndi.h>
29 #include <sys/pci_impl.h>
30 #include <sys/pci_cfgspace.h>
31 #include <sys/pci_cfgspace_impl.h>
32 #include <sys/memlist.h>
33 #include <sys/bootconf.h>
37 * pci irq routing information table
40 static pci_irq_route_t
*pci_irq_routes
;
43 static int pci_bios_get_irq_routing(pci_irq_route_t
*, int, int *);
44 static void pci_get_irq_routing_table(void);
48 * Retrieve information from the bios needed for system
49 * configuration early during startup.
52 startup_pci_bios(void)
54 pci_get_irq_routing_table();
59 * Issue the bios get irq routing information table interrupt
61 * Despite the name, the information in the table is only
62 * used to derive slot names for some named pci hot-plug slots.
64 * Returns the number of irq routing table entries returned
65 * by the bios, or 0 and optionally, the number of entries required.
68 pci_bios_get_irq_routing(pci_irq_route_t
*routes
, int nroutes
, int *nneededp
)
79 /* in UEFI system, there is no BIOS data */
80 if (BOP_GETPROPLEN(bootops
, "efi-systab") > 0)
84 * Set up irq routing header with the size and address
85 * of some useable low-memory data addresses. Initalize
86 * data area to zero, avoiding memcpy/bzero.
88 hdrp
= (uchar_t
*)BIOS_IRQ_ROUTING_HDR
;
89 bufp
= (uchar_t
*)BIOS_IRQ_ROUTING_DATA
;
91 n
= nroutes
* sizeof (pci_irq_route_t
);
92 for (i
= 0; i
< n
; i
++)
94 ((pci_irq_route_hdr_t
*)hdrp
)->pir_size
= n
;
95 ((pci_irq_route_hdr_t
*)hdrp
)->pir_addr
= (uint32_t)(uintptr_t)bufp
;
97 bzero(®s
, sizeof (regs
));
98 regs
.eax
.word
.ax
= (PCI_FUNCTION_ID
<< 8) | PCI_GET_IRQ_ROUTING
;
101 regs
.es
= FP_SEG((uint_t
)(uintptr_t)hdrp
);
102 regs
.edi
.word
.di
= FP_OFF((uint_t
)(uintptr_t)hdrp
);
104 BOP_DOINT(bootops
, 0x1a, ®s
);
106 n
= (int)(((pci_irq_route_hdr_t
*)hdrp
)->pir_size
/
107 sizeof (pci_irq_route_t
));
109 if ((regs
.eflags
& PS_C
) != 0) {
114 * Copy resulting irq routing data from low memory up to
115 * the kernel address space, avoiding memcpy as usual.
118 for (i
= 0; i
< n
* sizeof (pci_irq_route_t
); i
++)
119 ((uchar_t
*)routes
)[i
] = bufp
[i
];
127 pci_get_irq_routing_table(void)
129 pci_irq_route_t
*routes
;
130 int n
= N_PCI_IRQ_ROUTES
;
135 * Get irq routing table information.
136 * Allocate a buffer for an initial default number of entries.
137 * If the bios indicates it needs a larger buffer, try it again.
138 * Drive on if it still won't cooperate and play nice after that.
140 routes
= kmem_zalloc(n
* sizeof (pci_irq_route_t
), KM_SLEEP
);
141 nroutes
= pci_bios_get_irq_routing(routes
, n
, &nneeded
);
142 if (nroutes
== 0 && nneeded
> n
) {
143 kmem_free(routes
, n
* sizeof (pci_irq_route_t
));
144 if (nneeded
> N_PCI_IRQ_ROUTES_MAX
) {
146 "pci: unable to get IRQ routing information, "
147 "required buffer space of %d entries exceeds max\n",
152 routes
= kmem_zalloc(n
* sizeof (pci_irq_route_t
), KM_SLEEP
);
153 nroutes
= pci_bios_get_irq_routing(routes
, n
, NULL
);
156 "pci: unable to get IRQ routing information, "
157 "required buffer space for %d entries\n", n
);
158 kmem_free(routes
, n
* sizeof (pci_irq_route_t
));
163 pci_irq_routes
= routes
;
164 pci_irq_nroutes
= nroutes
;
169 * Use the results of the PCI BIOS call that returned the routing tables
170 * to build the 1275 slot-names property for the indicated bus.
171 * Results are returned in buf. Length is return value, -1 is returned on
172 * overflow and zero is returned if no data exists to build a property.
175 pci_slot_names_prop(int bus
, char *buf
, int len
)
178 uchar_t slot
[N_PCI_IRQ_ROUTES_MAX
+1];
182 ASSERT(pci_irq_nroutes
<= N_PCI_IRQ_ROUTES_MAX
);
184 if (pci_irq_nroutes
== 0)
188 for (i
= 0; i
< pci_irq_nroutes
; i
++)
190 for (i
= 0; i
< pci_irq_nroutes
; i
++) {
191 if (pci_irq_routes
[i
].pir_bus
!= bus
)
193 if (pci_irq_routes
[i
].pir_slot
!= 0) {
194 dev
= (pci_irq_routes
[i
].pir_dev
& 0xf8) >> 3;
195 slot
[dev
] = pci_irq_routes
[i
].pir_slot
;
204 if (len
< (4 + nnames
* 8))
206 *(uint32_t *)buf
= mask
;
208 for (i
= 0; i
< pci_irq_nroutes
; i
++) {
211 (void) sprintf(buf
+ plen
, "Slot%d", slot
[i
]);
212 plen
+= strlen(buf
+plen
) + 1;
215 for (; plen
% 4; plen
++)