diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/pci/hotplug/cpqphp_nvram.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/pci/hotplug/cpqphp_nvram.c')
-rw-r--r-- | drivers/pci/hotplug/cpqphp_nvram.c | 666 |
1 files changed, 666 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c new file mode 100644 index 000000000000..ac98a11bd1eb --- /dev/null +++ b/drivers/pci/hotplug/cpqphp_nvram.c | |||
@@ -0,0 +1,666 @@ | |||
1 | /* | ||
2 | * Compaq Hot Plug Controller Driver | ||
3 | * | ||
4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
6 | * Copyright (C) 2001 IBM Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
13 | * your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | * Send feedback to <greg@kroah.com> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/workqueue.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <asm/uaccess.h> | ||
39 | #include "cpqphp.h" | ||
40 | #include "cpqphp_nvram.h" | ||
41 | |||
42 | |||
43 | #define ROM_INT15_PHY_ADDR 0x0FF859 | ||
44 | #define READ_EV 0xD8A4 | ||
45 | #define WRITE_EV 0xD8A5 | ||
46 | |||
47 | struct register_foo { | ||
48 | union { | ||
49 | unsigned long lword; /* eax */ | ||
50 | unsigned short word; /* ax */ | ||
51 | |||
52 | struct { | ||
53 | unsigned char low; /* al */ | ||
54 | unsigned char high; /* ah */ | ||
55 | } byte; | ||
56 | } data; | ||
57 | |||
58 | unsigned char opcode; /* see below */ | ||
59 | unsigned long length; /* if the reg. is a pointer, how much data */ | ||
60 | } __attribute__ ((packed)); | ||
61 | |||
62 | struct all_reg { | ||
63 | struct register_foo eax_reg; | ||
64 | struct register_foo ebx_reg; | ||
65 | struct register_foo ecx_reg; | ||
66 | struct register_foo edx_reg; | ||
67 | struct register_foo edi_reg; | ||
68 | struct register_foo esi_reg; | ||
69 | struct register_foo eflags_reg; | ||
70 | } __attribute__ ((packed)); | ||
71 | |||
72 | |||
73 | struct ev_hrt_header { | ||
74 | u8 Version; | ||
75 | u8 num_of_ctrl; | ||
76 | u8 next; | ||
77 | }; | ||
78 | |||
79 | struct ev_hrt_ctrl { | ||
80 | u8 bus; | ||
81 | u8 device; | ||
82 | u8 function; | ||
83 | u8 mem_avail; | ||
84 | u8 p_mem_avail; | ||
85 | u8 io_avail; | ||
86 | u8 bus_avail; | ||
87 | u8 next; | ||
88 | }; | ||
89 | |||
90 | |||
91 | static u8 evbuffer_init; | ||
92 | static u8 evbuffer_length; | ||
93 | static u8 evbuffer[1024]; | ||
94 | |||
95 | static void __iomem *compaq_int15_entry_point; | ||
96 | |||
97 | static spinlock_t int15_lock; /* lock for ordering int15_bios_call() */ | ||
98 | |||
99 | |||
100 | /* This is a series of function that deals with | ||
101 | setting & getting the hotplug resource table in some environment variable. | ||
102 | */ | ||
103 | |||
104 | /* | ||
105 | * We really shouldn't be doing this unless there is a _very_ good reason to!!! | ||
106 | * greg k-h | ||
107 | */ | ||
108 | |||
109 | |||
110 | static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail) | ||
111 | { | ||
112 | u8 **tByte; | ||
113 | |||
114 | if ((*used + 1) > *avail) | ||
115 | return(1); | ||
116 | |||
117 | *((u8*)*p_buffer) = value; | ||
118 | tByte = (u8**)p_buffer; | ||
119 | (*tByte)++; | ||
120 | *used+=1; | ||
121 | return(0); | ||
122 | } | ||
123 | |||
124 | |||
125 | static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail) | ||
126 | { | ||
127 | if ((*used + 4) > *avail) | ||
128 | return(1); | ||
129 | |||
130 | **p_buffer = value; | ||
131 | (*p_buffer)++; | ||
132 | *used+=4; | ||
133 | return(0); | ||
134 | } | ||
135 | |||
136 | |||
137 | /* | ||
138 | * check_for_compaq_ROM | ||
139 | * | ||
140 | * this routine verifies that the ROM OEM string is 'COMPAQ' | ||
141 | * | ||
142 | * returns 0 for non-Compaq ROM, 1 for Compaq ROM | ||
143 | */ | ||
144 | static int check_for_compaq_ROM (void __iomem *rom_start) | ||
145 | { | ||
146 | u8 temp1, temp2, temp3, temp4, temp5, temp6; | ||
147 | int result = 0; | ||
148 | |||
149 | temp1 = readb(rom_start + 0xffea + 0); | ||
150 | temp2 = readb(rom_start + 0xffea + 1); | ||
151 | temp3 = readb(rom_start + 0xffea + 2); | ||
152 | temp4 = readb(rom_start + 0xffea + 3); | ||
153 | temp5 = readb(rom_start + 0xffea + 4); | ||
154 | temp6 = readb(rom_start + 0xffea + 5); | ||
155 | if ((temp1 == 'C') && | ||
156 | (temp2 == 'O') && | ||
157 | (temp3 == 'M') && | ||
158 | (temp4 == 'P') && | ||
159 | (temp5 == 'A') && | ||
160 | (temp6 == 'Q')) { | ||
161 | result = 1; | ||
162 | } | ||
163 | dbg ("%s - returned %d\n", __FUNCTION__, result); | ||
164 | return result; | ||
165 | } | ||
166 | |||
167 | |||
168 | static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size) | ||
169 | { | ||
170 | unsigned long flags; | ||
171 | int op = operation; | ||
172 | int ret_val; | ||
173 | |||
174 | if (!compaq_int15_entry_point) | ||
175 | return -ENODEV; | ||
176 | |||
177 | spin_lock_irqsave(&int15_lock, flags); | ||
178 | __asm__ ( | ||
179 | "xorl %%ebx,%%ebx\n" \ | ||
180 | "xorl %%edx,%%edx\n" \ | ||
181 | "pushf\n" \ | ||
182 | "push %%cs\n" \ | ||
183 | "cli\n" \ | ||
184 | "call *%6\n" | ||
185 | : "=c" (*buf_size), "=a" (ret_val) | ||
186 | : "a" (op), "c" (*buf_size), "S" (ev_name), | ||
187 | "D" (buffer), "m" (compaq_int15_entry_point) | ||
188 | : "%ebx", "%edx"); | ||
189 | spin_unlock_irqrestore(&int15_lock, flags); | ||
190 | |||
191 | return((ret_val & 0xFF00) >> 8); | ||
192 | } | ||
193 | |||
194 | |||
195 | /* | ||
196 | * load_HRT | ||
197 | * | ||
198 | * Read the hot plug Resource Table from NVRAM | ||
199 | */ | ||
200 | static int load_HRT (void __iomem *rom_start) | ||
201 | { | ||
202 | u32 available; | ||
203 | u32 temp_dword; | ||
204 | u8 temp_byte = 0xFF; | ||
205 | u32 rc; | ||
206 | |||
207 | if (!check_for_compaq_ROM(rom_start)) { | ||
208 | return -ENODEV; | ||
209 | } | ||
210 | |||
211 | available = 1024; | ||
212 | |||
213 | // Now load the EV | ||
214 | temp_dword = available; | ||
215 | |||
216 | rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword); | ||
217 | |||
218 | evbuffer_length = temp_dword; | ||
219 | |||
220 | // We're maintaining the resource lists so write FF to invalidate old info | ||
221 | temp_dword = 1; | ||
222 | |||
223 | rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword); | ||
224 | |||
225 | return rc; | ||
226 | } | ||
227 | |||
228 | |||
229 | /* | ||
230 | * store_HRT | ||
231 | * | ||
232 | * Save the hot plug Resource Table in NVRAM | ||
233 | */ | ||
234 | static u32 store_HRT (void __iomem *rom_start) | ||
235 | { | ||
236 | u32 *buffer; | ||
237 | u32 *pFill; | ||
238 | u32 usedbytes; | ||
239 | u32 available; | ||
240 | u32 temp_dword; | ||
241 | u32 rc; | ||
242 | u8 loop; | ||
243 | u8 numCtrl = 0; | ||
244 | struct controller *ctrl; | ||
245 | struct pci_resource *resNode; | ||
246 | struct ev_hrt_header *p_EV_header; | ||
247 | struct ev_hrt_ctrl *p_ev_ctrl; | ||
248 | |||
249 | available = 1024; | ||
250 | |||
251 | if (!check_for_compaq_ROM(rom_start)) { | ||
252 | return(1); | ||
253 | } | ||
254 | |||
255 | buffer = (u32*) evbuffer; | ||
256 | |||
257 | if (!buffer) | ||
258 | return(1); | ||
259 | |||
260 | pFill = buffer; | ||
261 | usedbytes = 0; | ||
262 | |||
263 | p_EV_header = (struct ev_hrt_header *) pFill; | ||
264 | |||
265 | ctrl = cpqhp_ctrl_list; | ||
266 | |||
267 | // The revision of this structure | ||
268 | rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available); | ||
269 | if (rc) | ||
270 | return(rc); | ||
271 | |||
272 | // The number of controllers | ||
273 | rc = add_byte( &pFill, 1, &usedbytes, &available); | ||
274 | if (rc) | ||
275 | return(rc); | ||
276 | |||
277 | while (ctrl) { | ||
278 | p_ev_ctrl = (struct ev_hrt_ctrl *) pFill; | ||
279 | |||
280 | numCtrl++; | ||
281 | |||
282 | // The bus number | ||
283 | rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available); | ||
284 | if (rc) | ||
285 | return(rc); | ||
286 | |||
287 | // The device Number | ||
288 | rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); | ||
289 | if (rc) | ||
290 | return(rc); | ||
291 | |||
292 | // The function Number | ||
293 | rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available); | ||
294 | if (rc) | ||
295 | return(rc); | ||
296 | |||
297 | // Skip the number of available entries | ||
298 | rc = add_dword( &pFill, 0, &usedbytes, &available); | ||
299 | if (rc) | ||
300 | return(rc); | ||
301 | |||
302 | // Figure out memory Available | ||
303 | |||
304 | resNode = ctrl->mem_head; | ||
305 | |||
306 | loop = 0; | ||
307 | |||
308 | while (resNode) { | ||
309 | loop ++; | ||
310 | |||
311 | // base | ||
312 | rc = add_dword( &pFill, resNode->base, &usedbytes, &available); | ||
313 | if (rc) | ||
314 | return(rc); | ||
315 | |||
316 | // length | ||
317 | rc = add_dword( &pFill, resNode->length, &usedbytes, &available); | ||
318 | if (rc) | ||
319 | return(rc); | ||
320 | |||
321 | resNode = resNode->next; | ||
322 | } | ||
323 | |||
324 | // Fill in the number of entries | ||
325 | p_ev_ctrl->mem_avail = loop; | ||
326 | |||
327 | // Figure out prefetchable memory Available | ||
328 | |||
329 | resNode = ctrl->p_mem_head; | ||
330 | |||
331 | loop = 0; | ||
332 | |||
333 | while (resNode) { | ||
334 | loop ++; | ||
335 | |||
336 | // base | ||
337 | rc = add_dword( &pFill, resNode->base, &usedbytes, &available); | ||
338 | if (rc) | ||
339 | return(rc); | ||
340 | |||
341 | // length | ||
342 | rc = add_dword( &pFill, resNode->length, &usedbytes, &available); | ||
343 | if (rc) | ||
344 | return(rc); | ||
345 | |||
346 | resNode = resNode->next; | ||
347 | } | ||
348 | |||
349 | // Fill in the number of entries | ||
350 | p_ev_ctrl->p_mem_avail = loop; | ||
351 | |||
352 | // Figure out IO Available | ||
353 | |||
354 | resNode = ctrl->io_head; | ||
355 | |||
356 | loop = 0; | ||
357 | |||
358 | while (resNode) { | ||
359 | loop ++; | ||
360 | |||
361 | // base | ||
362 | rc = add_dword( &pFill, resNode->base, &usedbytes, &available); | ||
363 | if (rc) | ||
364 | return(rc); | ||
365 | |||
366 | // length | ||
367 | rc = add_dword( &pFill, resNode->length, &usedbytes, &available); | ||
368 | if (rc) | ||
369 | return(rc); | ||
370 | |||
371 | resNode = resNode->next; | ||
372 | } | ||
373 | |||
374 | // Fill in the number of entries | ||
375 | p_ev_ctrl->io_avail = loop; | ||
376 | |||
377 | // Figure out bus Available | ||
378 | |||
379 | resNode = ctrl->bus_head; | ||
380 | |||
381 | loop = 0; | ||
382 | |||
383 | while (resNode) { | ||
384 | loop ++; | ||
385 | |||
386 | // base | ||
387 | rc = add_dword( &pFill, resNode->base, &usedbytes, &available); | ||
388 | if (rc) | ||
389 | return(rc); | ||
390 | |||
391 | // length | ||
392 | rc = add_dword( &pFill, resNode->length, &usedbytes, &available); | ||
393 | if (rc) | ||
394 | return(rc); | ||
395 | |||
396 | resNode = resNode->next; | ||
397 | } | ||
398 | |||
399 | // Fill in the number of entries | ||
400 | p_ev_ctrl->bus_avail = loop; | ||
401 | |||
402 | ctrl = ctrl->next; | ||
403 | } | ||
404 | |||
405 | p_EV_header->num_of_ctrl = numCtrl; | ||
406 | |||
407 | // Now store the EV | ||
408 | |||
409 | temp_dword = usedbytes; | ||
410 | |||
411 | rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword); | ||
412 | |||
413 | dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword); | ||
414 | |||
415 | evbuffer_length = temp_dword; | ||
416 | |||
417 | if (rc) { | ||
418 | err(msg_unable_to_save); | ||
419 | return(1); | ||
420 | } | ||
421 | |||
422 | return(0); | ||
423 | } | ||
424 | |||
425 | |||
426 | void compaq_nvram_init (void __iomem *rom_start) | ||
427 | { | ||
428 | if (rom_start) { | ||
429 | compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); | ||
430 | } | ||
431 | dbg("int15 entry = %p\n", compaq_int15_entry_point); | ||
432 | |||
433 | /* initialize our int15 lock */ | ||
434 | spin_lock_init(&int15_lock); | ||
435 | } | ||
436 | |||
437 | |||
438 | int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) | ||
439 | { | ||
440 | u8 bus, device, function; | ||
441 | u8 nummem, numpmem, numio, numbus; | ||
442 | u32 rc; | ||
443 | u8 *p_byte; | ||
444 | struct pci_resource *mem_node; | ||
445 | struct pci_resource *p_mem_node; | ||
446 | struct pci_resource *io_node; | ||
447 | struct pci_resource *bus_node; | ||
448 | struct ev_hrt_ctrl *p_ev_ctrl; | ||
449 | struct ev_hrt_header *p_EV_header; | ||
450 | |||
451 | if (!evbuffer_init) { | ||
452 | // Read the resource list information in from NVRAM | ||
453 | if (load_HRT(rom_start)) | ||
454 | memset (evbuffer, 0, 1024); | ||
455 | |||
456 | evbuffer_init = 1; | ||
457 | } | ||
458 | |||
459 | // If we saved information in NVRAM, use it now | ||
460 | p_EV_header = (struct ev_hrt_header *) evbuffer; | ||
461 | |||
462 | // The following code is for systems where version 1.0 of this | ||
463 | // driver has been loaded, but doesn't support the hardware. | ||
464 | // In that case, the driver would incorrectly store something | ||
465 | // in NVRAM. | ||
466 | if ((p_EV_header->Version == 2) || | ||
467 | ((p_EV_header->Version == 1) && !ctrl->push_flag)) { | ||
468 | p_byte = &(p_EV_header->next); | ||
469 | |||
470 | p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next); | ||
471 | |||
472 | p_byte += 3; | ||
473 | |||
474 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) | ||
475 | return 2; | ||
476 | |||
477 | bus = p_ev_ctrl->bus; | ||
478 | device = p_ev_ctrl->device; | ||
479 | function = p_ev_ctrl->function; | ||
480 | |||
481 | while ((bus != ctrl->bus) || | ||
482 | (device != PCI_SLOT(ctrl->pci_dev->devfn)) || | ||
483 | (function != PCI_FUNC(ctrl->pci_dev->devfn))) { | ||
484 | nummem = p_ev_ctrl->mem_avail; | ||
485 | numpmem = p_ev_ctrl->p_mem_avail; | ||
486 | numio = p_ev_ctrl->io_avail; | ||
487 | numbus = p_ev_ctrl->bus_avail; | ||
488 | |||
489 | p_byte += 4; | ||
490 | |||
491 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) | ||
492 | return 2; | ||
493 | |||
494 | // Skip forward to the next entry | ||
495 | p_byte += (nummem + numpmem + numio + numbus) * 8; | ||
496 | |||
497 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) | ||
498 | return 2; | ||
499 | |||
500 | p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte; | ||
501 | |||
502 | p_byte += 3; | ||
503 | |||
504 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) | ||
505 | return 2; | ||
506 | |||
507 | bus = p_ev_ctrl->bus; | ||
508 | device = p_ev_ctrl->device; | ||
509 | function = p_ev_ctrl->function; | ||
510 | } | ||
511 | |||
512 | nummem = p_ev_ctrl->mem_avail; | ||
513 | numpmem = p_ev_ctrl->p_mem_avail; | ||
514 | numio = p_ev_ctrl->io_avail; | ||
515 | numbus = p_ev_ctrl->bus_avail; | ||
516 | |||
517 | p_byte += 4; | ||
518 | |||
519 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) | ||
520 | return 2; | ||
521 | |||
522 | while (nummem--) { | ||
523 | mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
524 | |||
525 | if (!mem_node) | ||
526 | break; | ||
527 | |||
528 | mem_node->base = *(u32*)p_byte; | ||
529 | dbg("mem base = %8.8x\n",mem_node->base); | ||
530 | p_byte += 4; | ||
531 | |||
532 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
533 | kfree(mem_node); | ||
534 | return 2; | ||
535 | } | ||
536 | |||
537 | mem_node->length = *(u32*)p_byte; | ||
538 | dbg("mem length = %8.8x\n",mem_node->length); | ||
539 | p_byte += 4; | ||
540 | |||
541 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
542 | kfree(mem_node); | ||
543 | return 2; | ||
544 | } | ||
545 | |||
546 | mem_node->next = ctrl->mem_head; | ||
547 | ctrl->mem_head = mem_node; | ||
548 | } | ||
549 | |||
550 | while (numpmem--) { | ||
551 | p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
552 | |||
553 | if (!p_mem_node) | ||
554 | break; | ||
555 | |||
556 | p_mem_node->base = *(u32*)p_byte; | ||
557 | dbg("pre-mem base = %8.8x\n",p_mem_node->base); | ||
558 | p_byte += 4; | ||
559 | |||
560 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
561 | kfree(p_mem_node); | ||
562 | return 2; | ||
563 | } | ||
564 | |||
565 | p_mem_node->length = *(u32*)p_byte; | ||
566 | dbg("pre-mem length = %8.8x\n",p_mem_node->length); | ||
567 | p_byte += 4; | ||
568 | |||
569 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
570 | kfree(p_mem_node); | ||
571 | return 2; | ||
572 | } | ||
573 | |||
574 | p_mem_node->next = ctrl->p_mem_head; | ||
575 | ctrl->p_mem_head = p_mem_node; | ||
576 | } | ||
577 | |||
578 | while (numio--) { | ||
579 | io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
580 | |||
581 | if (!io_node) | ||
582 | break; | ||
583 | |||
584 | io_node->base = *(u32*)p_byte; | ||
585 | dbg("io base = %8.8x\n",io_node->base); | ||
586 | p_byte += 4; | ||
587 | |||
588 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
589 | kfree(io_node); | ||
590 | return 2; | ||
591 | } | ||
592 | |||
593 | io_node->length = *(u32*)p_byte; | ||
594 | dbg("io length = %8.8x\n",io_node->length); | ||
595 | p_byte += 4; | ||
596 | |||
597 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
598 | kfree(io_node); | ||
599 | return 2; | ||
600 | } | ||
601 | |||
602 | io_node->next = ctrl->io_head; | ||
603 | ctrl->io_head = io_node; | ||
604 | } | ||
605 | |||
606 | while (numbus--) { | ||
607 | bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
608 | |||
609 | if (!bus_node) | ||
610 | break; | ||
611 | |||
612 | bus_node->base = *(u32*)p_byte; | ||
613 | p_byte += 4; | ||
614 | |||
615 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
616 | kfree(bus_node); | ||
617 | return 2; | ||
618 | } | ||
619 | |||
620 | bus_node->length = *(u32*)p_byte; | ||
621 | p_byte += 4; | ||
622 | |||
623 | if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { | ||
624 | kfree(bus_node); | ||
625 | return 2; | ||
626 | } | ||
627 | |||
628 | bus_node->next = ctrl->bus_head; | ||
629 | ctrl->bus_head = bus_node; | ||
630 | } | ||
631 | |||
632 | // If all of the following fail, we don't have any resources for | ||
633 | // hot plug add | ||
634 | rc = 1; | ||
635 | rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); | ||
636 | rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
637 | rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head)); | ||
638 | rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
639 | |||
640 | if (rc) | ||
641 | return(rc); | ||
642 | } else { | ||
643 | if ((evbuffer[0] != 0) && (!ctrl->push_flag)) | ||
644 | return 1; | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | |||
651 | int compaq_nvram_store (void __iomem *rom_start) | ||
652 | { | ||
653 | int rc = 1; | ||
654 | |||
655 | if (rom_start == NULL) | ||
656 | return -ENODEV; | ||
657 | |||
658 | if (evbuffer_init) { | ||
659 | rc = store_HRT(rom_start); | ||
660 | if (rc) { | ||
661 | err(msg_unable_to_save); | ||
662 | } | ||
663 | } | ||
664 | return rc; | ||
665 | } | ||
666 | |||