Commit | Line | Data |
---|---|---|
8ea6091f JK |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved. | |
7 | */ | |
8 | ||
9 | #include <asm/sn/types.h> | |
10 | #include <asm/sn/addrs.h> | |
11 | #include <asm/sn/pcidev.h> | |
12 | #include <asm/sn/pcibus_provider_defs.h> | |
13 | #include <asm/sn/sn_sal.h> | |
14 | #include "xtalk/hubdev.h" | |
15 | #include <linux/acpi.h> | |
6f09a925 | 16 | #include <acpi/acnamesp.h> |
8ea6091f JK |
17 | |
18 | ||
19 | /* | |
20 | * The code in this file will only be executed when running with | |
21 | * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1) | |
22 | */ | |
23 | ||
24 | ||
25 | /* | |
26 | * This value must match the UUID the PROM uses | |
27 | * (io/acpi/defblk.c) when building a vendor descriptor. | |
28 | */ | |
29 | struct acpi_vendor_uuid sn_uuid = { | |
30 | .subtype = 0, | |
31 | .data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11, | |
32 | 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 }, | |
33 | }; | |
34 | ||
6f09a925 JK |
35 | struct sn_pcidev_match { |
36 | u8 bus; | |
37 | unsigned int devfn; | |
38 | acpi_handle handle; | |
39 | }; | |
40 | ||
8ea6091f JK |
41 | /* |
42 | * Perform the early IO init in PROM. | |
43 | */ | |
44 | static s64 | |
45 | sal_ioif_init(u64 *result) | |
46 | { | |
47 | struct ia64_sal_retval isrv = {0,0,0,0}; | |
48 | ||
49 | SAL_CALL_NOLOCK(isrv, | |
50 | SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0); | |
51 | *result = isrv.v0; | |
52 | return isrv.status; | |
53 | } | |
54 | ||
55 | /* | |
690b8d9d JK |
56 | * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback() |
57 | * for all SGIHUB and SGITIO acpi devices defined in the | |
58 | * DSDT. It obtains the hubdev_info pointer from the | |
59 | * ACPI vendor resource, which the PROM setup, and sets up the | |
60 | * hubdev_info in the pda. | |
8ea6091f | 61 | */ |
690b8d9d JK |
62 | |
63 | static acpi_status __init | |
64 | sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret) | |
8ea6091f JK |
65 | { |
66 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
67 | u64 addr; | |
68 | struct hubdev_info *hubdev; | |
69 | struct hubdev_info *hubdev_ptr; | |
70 | int i; | |
71 | u64 nasid; | |
72 | struct acpi_resource *resource; | |
8ea6091f JK |
73 | acpi_status status; |
74 | struct acpi_resource_vendor_typed *vendor; | |
75 | extern void sn_common_hubdev_init(struct hubdev_info *); | |
76 | ||
690b8d9d | 77 | status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, |
8ea6091f JK |
78 | &sn_uuid, &buffer); |
79 | if (ACPI_FAILURE(status)) { | |
80 | printk(KERN_ERR | |
690b8d9d JK |
81 | "sn_acpi_hubdev_init: acpi_get_vendor_resource() " |
82 | "(0x%x) failed for: ", status); | |
83 | acpi_ns_print_node_pathname(handle, NULL); | |
84 | printk("\n"); | |
85 | return AE_OK; /* Continue walking namespace */ | |
8ea6091f JK |
86 | } |
87 | ||
88 | resource = buffer.pointer; | |
89 | vendor = &resource->data.vendor_typed; | |
90 | if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != | |
91 | sizeof(struct hubdev_info *)) { | |
92 | printk(KERN_ERR | |
690b8d9d | 93 | "sn_acpi_hubdev_init: Invalid vendor data length: %d for: ", |
8ea6091f | 94 | vendor->byte_length); |
690b8d9d JK |
95 | acpi_ns_print_node_pathname(handle, NULL); |
96 | printk("\n"); | |
8ea6091f JK |
97 | goto exit; |
98 | } | |
99 | ||
100 | memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *)); | |
101 | hubdev_ptr = __va((struct hubdev_info *) addr); | |
102 | ||
103 | nasid = hubdev_ptr->hdi_nasid; | |
104 | i = nasid_to_cnodeid(nasid); | |
105 | hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo); | |
106 | *hubdev = *hubdev_ptr; | |
107 | sn_common_hubdev_init(hubdev); | |
108 | ||
109 | exit: | |
110 | kfree(buffer.pointer); | |
690b8d9d | 111 | return AE_OK; /* Continue walking namespace */ |
8ea6091f JK |
112 | } |
113 | ||
114 | /* | |
115 | * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in | |
116 | * the ACPI Vendor resource for this bus. | |
117 | */ | |
118 | static struct pcibus_bussoft * | |
119 | sn_get_bussoft_ptr(struct pci_bus *bus) | |
120 | { | |
121 | u64 addr; | |
122 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
123 | acpi_handle handle; | |
124 | struct pcibus_bussoft *prom_bussoft_ptr; | |
125 | struct acpi_resource *resource; | |
126 | acpi_status status; | |
127 | struct acpi_resource_vendor_typed *vendor; | |
128 | ||
129 | ||
130 | handle = PCI_CONTROLLER(bus)->acpi_handle; | |
131 | status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, | |
132 | &sn_uuid, &buffer); | |
133 | if (ACPI_FAILURE(status)) { | |
6f09a925 JK |
134 | printk(KERN_ERR "%s: " |
135 | "acpi_get_vendor_resource() failed (0x%x) for: ", | |
d4ed8084 | 136 | __func__, status); |
6f09a925 JK |
137 | acpi_ns_print_node_pathname(handle, NULL); |
138 | printk("\n"); | |
8ea6091f JK |
139 | return NULL; |
140 | } | |
141 | resource = buffer.pointer; | |
142 | vendor = &resource->data.vendor_typed; | |
143 | ||
144 | if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != | |
145 | sizeof(struct pcibus_bussoft *)) { | |
146 | printk(KERN_ERR | |
6f09a925 | 147 | "%s: Invalid vendor data length %d\n", |
d4ed8084 | 148 | __func__, vendor->byte_length); |
8ea6091f JK |
149 | kfree(buffer.pointer); |
150 | return NULL; | |
151 | } | |
152 | memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *)); | |
153 | prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr); | |
154 | kfree(buffer.pointer); | |
155 | ||
156 | return prom_bussoft_ptr; | |
157 | } | |
158 | ||
159 | /* | |
6f09a925 JK |
160 | * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info |
161 | * pointers from the vendor resource using the | |
162 | * provided acpi handle, and copy the structures | |
163 | * into the argument buffers. | |
8ea6091f | 164 | */ |
6f09a925 JK |
165 | static int |
166 | sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info, | |
167 | struct sn_irq_info **sn_irq_info) | |
8ea6091f | 168 | { |
6f09a925 JK |
169 | u64 addr; |
170 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
171 | struct sn_irq_info *irq_info, *irq_info_prom; | |
172 | struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr; | |
173 | struct acpi_resource *resource; | |
174 | int ret = 0; | |
175 | acpi_status status; | |
176 | struct acpi_resource_vendor_typed *vendor; | |
8ea6091f | 177 | |
6f09a925 JK |
178 | /* |
179 | * The pointer to this device's pcidev_info structure in | |
180 | * the PROM, is in the vendor resource. | |
181 | */ | |
182 | status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, | |
183 | &sn_uuid, &buffer); | |
184 | if (ACPI_FAILURE(status)) { | |
185 | printk(KERN_ERR | |
186 | "%s: acpi_get_vendor_resource() failed (0x%x) for: ", | |
d4ed8084 | 187 | __func__, status); |
6f09a925 JK |
188 | acpi_ns_print_node_pathname(handle, NULL); |
189 | printk("\n"); | |
190 | return 1; | |
191 | } | |
192 | ||
193 | resource = buffer.pointer; | |
194 | vendor = &resource->data.vendor_typed; | |
195 | if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != | |
196 | sizeof(struct pci_devdev_info *)) { | |
197 | printk(KERN_ERR | |
198 | "%s: Invalid vendor data length: %d for: ", | |
d4ed8084 | 199 | __func__, vendor->byte_length); |
6f09a925 JK |
200 | acpi_ns_print_node_pathname(handle, NULL); |
201 | printk("\n"); | |
202 | ret = 1; | |
203 | goto exit; | |
204 | } | |
205 | ||
206 | pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); | |
207 | if (!pcidev_ptr) | |
d4ed8084 | 208 | panic("%s: Unable to alloc memory for pcidev_info", __func__); |
6f09a925 JK |
209 | |
210 | memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *)); | |
211 | pcidev_prom_ptr = __va(addr); | |
212 | memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info)); | |
213 | ||
214 | /* Get the IRQ info */ | |
215 | irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); | |
216 | if (!irq_info) | |
d4ed8084 | 217 | panic("%s: Unable to alloc memory for sn_irq_info", __func__); |
6f09a925 JK |
218 | |
219 | if (pcidev_ptr->pdi_sn_irq_info) { | |
220 | irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info); | |
221 | memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info)); | |
222 | } | |
223 | ||
224 | *pcidev_info = pcidev_ptr; | |
225 | *sn_irq_info = irq_info; | |
226 | ||
227 | exit: | |
228 | kfree(buffer.pointer); | |
229 | return ret; | |
230 | } | |
231 | ||
232 | static unsigned int | |
233 | get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle) | |
234 | { | |
27663c58 | 235 | unsigned long long adr; |
6f09a925 JK |
236 | acpi_handle child; |
237 | unsigned int devfn; | |
238 | int function; | |
239 | acpi_handle parent; | |
240 | int slot; | |
241 | acpi_status status; | |
242 | ||
243 | /* | |
244 | * Do an upward search to find the root bus device, and | |
245 | * obtain the host devfn from the previous child device. | |
246 | */ | |
247 | child = device_handle; | |
248 | while (child) { | |
249 | status = acpi_get_parent(child, &parent); | |
250 | if (ACPI_FAILURE(status)) { | |
251 | printk(KERN_ERR "%s: acpi_get_parent() failed " | |
d4ed8084 | 252 | "(0x%x) for: ", __func__, status); |
6f09a925 JK |
253 | acpi_ns_print_node_pathname(child, NULL); |
254 | printk("\n"); | |
d4ed8084 | 255 | panic("%s: Unable to find host devfn\n", __func__); |
6f09a925 JK |
256 | } |
257 | if (parent == rootbus_handle) | |
258 | break; | |
259 | child = parent; | |
260 | } | |
261 | if (!child) { | |
262 | printk(KERN_ERR "%s: Unable to find root bus for: ", | |
d4ed8084 | 263 | __func__); |
6f09a925 JK |
264 | acpi_ns_print_node_pathname(device_handle, NULL); |
265 | printk("\n"); | |
266 | BUG(); | |
267 | } | |
268 | ||
269 | status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr); | |
270 | if (ACPI_FAILURE(status)) { | |
271 | printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ", | |
d4ed8084 | 272 | __func__, status); |
6f09a925 JK |
273 | acpi_ns_print_node_pathname(child, NULL); |
274 | printk("\n"); | |
d4ed8084 | 275 | panic("%s: Unable to find host devfn\n", __func__); |
6f09a925 JK |
276 | } |
277 | ||
278 | slot = (adr >> 16) & 0xffff; | |
279 | function = adr & 0xffff; | |
280 | devfn = PCI_DEVFN(slot, function); | |
281 | return devfn; | |
282 | } | |
283 | ||
284 | /* | |
285 | * find_matching_device - Callback routine to find the ACPI device | |
286 | * that matches up with our pci_dev device. | |
287 | * Matching is done on bus number and devfn. | |
288 | * To find the bus number for a particular | |
289 | * ACPI device, we must look at the _BBN method | |
290 | * of its parent. | |
291 | */ | |
292 | static acpi_status | |
293 | find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv) | |
294 | { | |
27663c58 MW |
295 | unsigned long long bbn = -1; |
296 | unsigned long long adr; | |
6f09a925 JK |
297 | acpi_handle parent = NULL; |
298 | acpi_status status; | |
299 | unsigned int devfn; | |
300 | int function; | |
301 | int slot; | |
302 | struct sn_pcidev_match *info = context; | |
303 | ||
304 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, | |
305 | &adr); | |
306 | if (ACPI_SUCCESS(status)) { | |
307 | status = acpi_get_parent(handle, &parent); | |
308 | if (ACPI_FAILURE(status)) { | |
8ea6091f | 309 | printk(KERN_ERR |
6f09a925 | 310 | "%s: acpi_get_parent() failed (0x%x) for: ", |
d4ed8084 | 311 | __func__, status); |
6f09a925 JK |
312 | acpi_ns_print_node_pathname(handle, NULL); |
313 | printk("\n"); | |
314 | return AE_OK; | |
315 | } | |
316 | status = acpi_evaluate_integer(parent, METHOD_NAME__BBN, | |
317 | NULL, &bbn); | |
318 | if (ACPI_FAILURE(status)) { | |
319 | printk(KERN_ERR | |
320 | "%s: Failed to find _BBN in parent of: ", | |
d4ed8084 | 321 | __func__); |
6f09a925 JK |
322 | acpi_ns_print_node_pathname(handle, NULL); |
323 | printk("\n"); | |
324 | return AE_OK; | |
325 | } | |
326 | ||
327 | slot = (adr >> 16) & 0xffff; | |
328 | function = adr & 0xffff; | |
329 | devfn = PCI_DEVFN(slot, function); | |
330 | if ((info->devfn == devfn) && (info->bus == bbn)) { | |
331 | /* We have a match! */ | |
332 | info->handle = handle; | |
333 | return 1; | |
8ea6091f | 334 | } |
8ea6091f | 335 | } |
6f09a925 JK |
336 | return AE_OK; |
337 | } | |
338 | ||
339 | /* | |
340 | * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi | |
341 | * device matching the specified pci_dev, | |
342 | * and return the pcidev info and irq info. | |
343 | */ | |
344 | int | |
345 | sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info, | |
346 | struct sn_irq_info **sn_irq_info) | |
347 | { | |
348 | unsigned int host_devfn; | |
349 | struct sn_pcidev_match pcidev_match; | |
350 | acpi_handle rootbus_handle; | |
27663c58 | 351 | unsigned long long segment; |
6f09a925 JK |
352 | acpi_status status; |
353 | ||
354 | rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle; | |
355 | status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL, | |
356 | &segment); | |
357 | if (ACPI_SUCCESS(status)) { | |
358 | if (segment != pci_domain_nr(dev)) { | |
359 | printk(KERN_ERR | |
360 | "%s: Segment number mismatch, 0x%lx vs 0x%x for: ", | |
d4ed8084 | 361 | __func__, segment, pci_domain_nr(dev)); |
6f09a925 JK |
362 | acpi_ns_print_node_pathname(rootbus_handle, NULL); |
363 | printk("\n"); | |
364 | return 1; | |
365 | } | |
366 | } else { | |
367 | printk(KERN_ERR "%s: Unable to get __SEG from: ", | |
d4ed8084 | 368 | __func__); |
6f09a925 JK |
369 | acpi_ns_print_node_pathname(rootbus_handle, NULL); |
370 | printk("\n"); | |
371 | return 1; | |
372 | } | |
373 | ||
374 | /* | |
375 | * We want to search all devices in this segment/domain | |
376 | * of the ACPI namespace for the matching ACPI device, | |
377 | * which holds the pcidev_info pointer in its vendor resource. | |
378 | */ | |
379 | pcidev_match.bus = dev->bus->number; | |
380 | pcidev_match.devfn = dev->devfn; | |
381 | pcidev_match.handle = NULL; | |
382 | ||
383 | acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX, | |
384 | find_matching_device, &pcidev_match, NULL); | |
385 | ||
386 | if (!pcidev_match.handle) { | |
387 | printk(KERN_ERR | |
388 | "%s: Could not find matching ACPI device for %s.\n", | |
d4ed8084 | 389 | __func__, pci_name(dev)); |
6f09a925 | 390 | return 1; |
8ea6091f | 391 | } |
6f09a925 JK |
392 | |
393 | if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info)) | |
394 | return 1; | |
395 | ||
396 | /* Build up the pcidev_info.pdi_slot_host_handle */ | |
397 | host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle); | |
398 | (*pcidev_info)->pdi_slot_host_handle = | |
399 | ((unsigned long) pci_domain_nr(dev) << 40) | | |
400 | /* bus == 0 */ | |
401 | host_devfn; | |
402 | return 0; | |
8ea6091f JK |
403 | } |
404 | ||
a2302c68 | 405 | /* |
6f09a925 JK |
406 | * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info. |
407 | * Perform any SN specific slot fixup. | |
a2302c68 JK |
408 | * At present there does not appear to be |
409 | * any generic way to handle a ROM image | |
410 | * that has been shadowed by the PROM, so | |
411 | * we pass a pointer to it within the | |
412 | * pcidev_info structure. | |
413 | */ | |
414 | ||
415 | void | |
6f09a925 | 416 | sn_acpi_slot_fixup(struct pci_dev *dev) |
a2302c68 JK |
417 | { |
418 | void __iomem *addr; | |
6f09a925 JK |
419 | struct pcidev_info *pcidev_info = NULL; |
420 | struct sn_irq_info *sn_irq_info = NULL; | |
d7ad2254 | 421 | size_t image_size, size; |
a2302c68 | 422 | |
6f09a925 JK |
423 | if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { |
424 | panic("%s: Failure obtaining pcidev_info for %s\n", | |
d4ed8084 | 425 | __func__, pci_name(dev)); |
6f09a925 JK |
426 | } |
427 | ||
a2302c68 JK |
428 | if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { |
429 | /* | |
430 | * A valid ROM image exists and has been shadowed by the | |
d7ad2254 JK |
431 | * PROM. Setup the pci_dev ROM resource with the address |
432 | * of the shadowed copy, and the actual length of the ROM image. | |
a2302c68 | 433 | */ |
d7ad2254 JK |
434 | size = pci_resource_len(dev, PCI_ROM_RESOURCE); |
435 | addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], | |
436 | size); | |
437 | image_size = pci_get_rom_size(addr, size); | |
a2302c68 JK |
438 | dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; |
439 | dev->resource[PCI_ROM_RESOURCE].end = | |
d7ad2254 | 440 | (unsigned long) addr + image_size - 1; |
a2302c68 JK |
441 | dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; |
442 | } | |
6f09a925 | 443 | sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); |
a2302c68 JK |
444 | } |
445 | ||
6f09a925 JK |
446 | EXPORT_SYMBOL(sn_acpi_slot_fixup); |
447 | ||
8ea6091f | 448 | |
6f09a925 JK |
449 | /* |
450 | * sn_acpi_bus_fixup - Perform SN specific setup of software structs | |
451 | * (pcibus_bussoft, pcidev_info) and hardware | |
452 | * registers, for the specified bus and devices under it. | |
453 | */ | |
454 | void | |
455 | sn_acpi_bus_fixup(struct pci_bus *bus) | |
456 | { | |
457 | struct pci_dev *pci_dev = NULL; | |
458 | struct pcibus_bussoft *prom_bussoft_ptr; | |
459 | ||
460 | if (!bus->parent) { /* If root bus */ | |
461 | prom_bussoft_ptr = sn_get_bussoft_ptr(bus); | |
462 | if (prom_bussoft_ptr == NULL) { | |
463 | printk(KERN_ERR | |
464 | "%s: 0x%04x:0x%02x Unable to " | |
465 | "obtain prom_bussoft_ptr\n", | |
d4ed8084 | 466 | __func__, pci_domain_nr(bus), bus->number); |
6f09a925 JK |
467 | return; |
468 | } | |
469 | sn_common_bus_fixup(bus, prom_bussoft_ptr); | |
470 | } | |
471 | list_for_each_entry(pci_dev, &bus->devices, bus_list) { | |
472 | sn_acpi_slot_fixup(pci_dev); | |
473 | } | |
474 | } | |
475 | ||
8ea6091f JK |
476 | /* |
477 | * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the | |
478 | * nodes and root buses in the DSDT. As a result, bus scanning | |
479 | * will be initiated by the Linux ACPI code. | |
480 | */ | |
481 | ||
482 | void __init | |
483 | sn_io_acpi_init(void) | |
484 | { | |
485 | u64 result; | |
486 | s64 status; | |
487 | ||
3948ec94 JK |
488 | /* SN Altix does not follow the IOSAPIC IRQ routing model */ |
489 | acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM; | |
490 | ||
690b8d9d JK |
491 | /* Setup hubdev_info for all SGIHUB/SGITIO devices */ |
492 | acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL); | |
493 | acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL); | |
494 | ||
8ea6091f JK |
495 | status = sal_ioif_init(&result); |
496 | if (status || result) | |
497 | panic("sal_ioif_init failed: [%lx] %s\n", | |
498 | status, ia64_sal_strerror(status)); | |
499 | } |