1/*
2 * IBM Hot Plug Controller Driver
3 *
4 * Written By: Irene Zubarev, IBM Corporation
5 *
6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
7 * Copyright (C) 2001,2002 IBM Corp.
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19 * NON INFRINGEMENT.  See the GNU General Public License for more
20 * details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * Send feedback to <gregkh@us.ibm.com>
27 *
28 */
29
30#include <linux/module.h>
31#include <linux/slab.h>
32#include <linux/pci.h>
33#include <linux/list.h>
34#include <linux/init.h>
35#include "ibmphp.h"
36
37static int flags = 0;		/* for testing */
38
39static void update_resources (struct bus_node *bus_cur, int type, int rangeno);
40static int once_over (void);
41static int remove_ranges (struct bus_node *, struct bus_node *);
42static int update_bridge_ranges (struct bus_node **);
43static int add_bus_range (int type, struct range_node *, struct bus_node *);
44static void fix_resources (struct bus_node *);
45static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
46
47static LIST_HEAD(gbuses);
48
49static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag)
50{
51	struct bus_node * newbus;
52
53	if (!(curr) && !(flag)) {
54		err ("NULL pointer passed\n");
55		return NULL;
56	}
57
58	newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
59	if (!newbus) {
60		err ("out of system memory\n");
61		return NULL;
62	}
63
64	if (flag)
65		newbus->busno = busno;
66	else
67		newbus->busno = curr->bus_num;
68	list_add_tail (&newbus->bus_list, &gbuses);
69	return newbus;
70}
71
72static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr)
73{
74	struct resource_node *rs;
75
76	if (!curr) {
77		err ("NULL passed to allocate\n");
78		return NULL;
79	}
80
81	rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
82	if (!rs) {
83		err ("out of system memory\n");
84		return NULL;
85	}
86	rs->busno = curr->bus_num;
87	rs->devfunc = curr->dev_fun;
88	rs->start = curr->start_addr;
89	rs->end = curr->end_addr;
90	rs->len = curr->end_addr - curr->start_addr + 1;
91	return rs;
92}
93
94static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus)
95{
96	struct bus_node * newbus;
97	struct range_node *newrange;
98	u8 num_ranges = 0;
99
100	if (first_bus) {
101		newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
102		if (!newbus) {
103			err ("out of system memory.\n");
104			return -ENOMEM;
105		}
106		newbus->busno = curr->bus_num;
107	} else {
108		newbus = *new_bus;
109		switch (flag) {
110			case MEM:
111				num_ranges = newbus->noMemRanges;
112				break;
113			case PFMEM:
114				num_ranges = newbus->noPFMemRanges;
115				break;
116			case IO:
117				num_ranges = newbus->noIORanges;
118				break;
119		}
120	}
121
122	newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL);
123	if (!newrange) {
124		if (first_bus)
125			kfree (newbus);
126		err ("out of system memory\n");
127		return -ENOMEM;
128	}
129	newrange->start = curr->start_addr;
130	newrange->end = curr->end_addr;
131
132	if (first_bus || (!num_ranges))
133		newrange->rangeno = 1;
134	else {
135		/* need to insert our range */
136		add_bus_range (flag, newrange, newbus);
137		debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
138	}
139
140	switch (flag) {
141		case MEM:
142			newbus->rangeMem = newrange;
143			if (first_bus)
144				newbus->noMemRanges = 1;
145			else {
146				debug ("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
147				++newbus->noMemRanges;
148				fix_resources (newbus);
149			}
150			break;
151		case IO:
152			newbus->rangeIO = newrange;
153			if (first_bus)
154				newbus->noIORanges = 1;
155			else {
156				debug ("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
157				++newbus->noIORanges;
158				fix_resources (newbus);
159			}
160			break;
161		case PFMEM:
162			newbus->rangePFMem = newrange;
163			if (first_bus)
164				newbus->noPFMemRanges = 1;
165			else {
166				debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
167				++newbus->noPFMemRanges;
168				fix_resources (newbus);
169			}
170
171			break;
172	}
173
174	*new_bus = newbus;
175	*new_range = newrange;
176	return 0;
177}
178
179
180/* Notes:
181 * 1. The ranges are ordered.  The buses are not ordered.  (First come)
182 *
183 * 2. If cannot allocate out of PFMem range, allocate from Mem ranges.  PFmemFromMem
184 * are not sorted. (no need since use mem node). To not change the entire code, we
185 * also add mem node whenever this case happens so as not to change
186 * ibmphp_check_mem_resource etc (and since it really is taking Mem resource)
187 */
188
189/*****************************************************************************
190 * This is the Resource Management initialization function.  It will go through
191 * the Resource list taken from EBDA and fill in this module's data structures
192 *
193 * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES,
194 * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW
195 *
196 * Input: ptr to the head of the resource list from EBDA
197 * Output: 0, -1 or error codes
198 ***************************************************************************/
199int __init ibmphp_rsrc_init (void)
200{
201	struct ebda_pci_rsrc *curr;
202	struct range_node *newrange = NULL;
203	struct bus_node *newbus = NULL;
204	struct bus_node *bus_cur;
205	struct bus_node *bus_prev;
206	struct list_head *tmp;
207	struct resource_node *new_io = NULL;
208	struct resource_node *new_mem = NULL;
209	struct resource_node *new_pfmem = NULL;
210	int rc;
211	struct list_head *tmp_ebda;
212
213	list_for_each (tmp_ebda, &ibmphp_ebda_pci_rsrc_head) {
214		curr = list_entry (tmp_ebda, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
215		if (!(curr->rsrc_type & PCIDEVMASK)) {
216			/* EBDA still lists non PCI devices, so ignore... */
217			debug ("this is not a PCI DEVICE in rsrc_init, please take care\n");
218			// continue;
219		}
220
221		/* this is a primary bus resource */
222		if (curr->rsrc_type & PRIMARYBUSMASK) {
223			/* memory */
224			if ((curr->rsrc_type & RESTYPE) == MMASK) {
225				/* no bus structure exists in place yet */
226				if (list_empty (&gbuses)) {
227					if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
228						return rc;
229					list_add_tail (&newbus->bus_list, &gbuses);
230					debug ("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
231				} else {
232					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
233					/* found our bus */
234					if (bus_cur) {
235						rc = alloc_bus_range (&bus_cur, &newrange, curr, MEM, 0);
236						if (rc)
237							return rc;
238					} else {
239						/* went through all the buses and didn't find ours, need to create a new bus node */
240						if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
241							return rc;
242
243						list_add_tail (&newbus->bus_list, &gbuses);
244						debug ("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
245					}
246				}
247			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
248				/* prefetchable memory */
249				if (list_empty (&gbuses)) {
250					/* no bus structure exists in place yet */
251					if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
252						return rc;
253					list_add_tail (&newbus->bus_list, &gbuses);
254					debug ("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
255				} else {
256					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
257					if (bus_cur) {
258						/* found our bus */
259						rc = alloc_bus_range (&bus_cur, &newrange, curr, PFMEM, 0);
260						if (rc)
261							return rc;
262					} else {
263						/* went through all the buses and didn't find ours, need to create a new bus node */
264						if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
265							return rc;
266						list_add_tail (&newbus->bus_list, &gbuses);
267						debug ("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
268					}
269				}
270			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
271				/* IO */
272				if (list_empty (&gbuses)) {
273					/* no bus structure exists in place yet */
274					if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
275						return rc;
276					list_add_tail (&newbus->bus_list, &gbuses);
277					debug ("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
278				} else {
279					bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
280					if (bus_cur) {
281						rc = alloc_bus_range (&bus_cur, &newrange, curr, IO, 0);
282						if (rc)
283							return rc;
284					} else {
285						/* went through all the buses and didn't find ours, need to create a new bus node */
286						if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
287							return rc;
288						list_add_tail (&newbus->bus_list, &gbuses);
289						debug ("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
290					}
291				}
292
293			} else {
294				;	/* type is reserved  WHAT TO DO IN THIS CASE???
295					   NOTHING TO DO??? */
296			}
297		} else {
298			/* regular pci device resource */
299			if ((curr->rsrc_type & RESTYPE) == MMASK) {
300				/* Memory resource */
301				new_mem = alloc_resources (curr);
302				if (!new_mem)
303					return -ENOMEM;
304				new_mem->type = MEM;
305				/*
306				 * if it didn't find the bus, means PCI dev
307				 * came b4 the Primary Bus info, so need to
308				 * create a bus rangeno becomes a problem...
309				 * assign a -1 and then update once the range
310				 * actually appears...
311				 */
312				if (ibmphp_add_resource (new_mem) < 0) {
313					newbus = alloc_error_bus (curr, 0, 0);
314					if (!newbus)
315						return -ENOMEM;
316					newbus->firstMem = new_mem;
317					++newbus->needMemUpdate;
318					new_mem->rangeno = -1;
319				}
320				debug ("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);
321
322			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
323				/* PFMemory resource */
324				new_pfmem = alloc_resources (curr);
325				if (!new_pfmem)
326					return -ENOMEM;
327				new_pfmem->type = PFMEM;
328				new_pfmem->fromMem = 0;
329				if (ibmphp_add_resource (new_pfmem) < 0) {
330					newbus = alloc_error_bus (curr, 0, 0);
331					if (!newbus)
332						return -ENOMEM;
333					newbus->firstPFMem = new_pfmem;
334					++newbus->needPFMemUpdate;
335					new_pfmem->rangeno = -1;
336				}
337
338				debug ("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
339			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
340				/* IO resource */
341				new_io = alloc_resources (curr);
342				if (!new_io)
343					return -ENOMEM;
344				new_io->type = IO;
345
346				/*
347				 * if it didn't find the bus, means PCI dev
348				 * came b4 the Primary Bus info, so need to
349				 * create a bus rangeno becomes a problem...
350				 * Can assign a -1 and then update once the
351				 * range actually appears...
352				 */
353				if (ibmphp_add_resource (new_io) < 0) {
354					newbus = alloc_error_bus (curr, 0, 0);
355					if (!newbus)
356						return -ENOMEM;
357					newbus->firstIO = new_io;
358					++newbus->needIOUpdate;
359					new_io->rangeno = -1;
360				}
361				debug ("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
362			}
363		}
364	}
365
366	list_for_each (tmp, &gbuses) {
367		bus_cur = list_entry (tmp, struct bus_node, bus_list);
368		/* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
369		rc = update_bridge_ranges (&bus_cur);
370		if (rc)
371			return rc;
372	}
373	rc = once_over ();  /* This is to align ranges (so no -1) */
374	if (rc)
375		return rc;
376	return 0;
377}
378
379/********************************************************************************
380 * This function adds a range into a sorted list of ranges per bus for a particular
381 * range type, it then calls another routine to update the range numbers on the
382 * pci devices' resources for the appropriate resource
383 *
384 * Input: type of the resource, range to add, current bus
385 * Output: 0 or -1, bus and range ptrs
386 ********************************************************************************/
387static int add_bus_range (int type, struct range_node *range, struct bus_node *bus_cur)
388{
389	struct range_node *range_cur = NULL;
390	struct range_node *range_prev;
391	int count = 0, i_init;
392	int noRanges = 0;
393
394	switch (type) {
395		case MEM:
396			range_cur = bus_cur->rangeMem;
397			noRanges = bus_cur->noMemRanges;
398			break;
399		case PFMEM:
400			range_cur = bus_cur->rangePFMem;
401			noRanges = bus_cur->noPFMemRanges;
402			break;
403		case IO:
404			range_cur = bus_cur->rangeIO;
405			noRanges = bus_cur->noIORanges;
406			break;
407	}
408
409	range_prev = NULL;
410	while (range_cur) {
411		if (range->start < range_cur->start)
412			break;
413		range_prev = range_cur;
414		range_cur = range_cur->next;
415		count = count + 1;
416	}
417	if (!count) {
418		/* our range will go at the beginning of the list */
419		switch (type) {
420			case MEM:
421				bus_cur->rangeMem = range;
422				break;
423			case PFMEM:
424				bus_cur->rangePFMem = range;
425				break;
426			case IO:
427				bus_cur->rangeIO = range;
428				break;
429		}
430		range->next = range_cur;
431		range->rangeno = 1;
432		i_init = 0;
433	} else if (!range_cur) {
434		/* our range will go at the end of the list */
435		range->next = NULL;
436		range_prev->next = range;
437		range->rangeno = range_prev->rangeno + 1;
438		return 0;
439	} else {
440		/* the range is in the middle */
441		range_prev->next = range;
442		range->next = range_cur;
443		range->rangeno = range_cur->rangeno;
444		i_init = range_prev->rangeno;
445	}
446
447	for (count = i_init; count < noRanges; ++count) {
448		++range_cur->rangeno;
449		range_cur = range_cur->next;
450	}
451
452	update_resources (bus_cur, type, i_init + 1);
453	return 0;
454}
455
456/*******************************************************************************
457 * This routine goes through the list of resources of type 'type' and updates
458 * the range numbers that they correspond to.  It was called from add_bus_range fnc
459 *
460 * Input: bus, type of the resource, the rangeno starting from which to update
461 ******************************************************************************/
462static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
463{
464	struct resource_node *res = NULL;
465	u8 eol = 0;	/* end of list indicator */
466
467	switch (type) {
468		case MEM:
469			if (bus_cur->firstMem)
470				res = bus_cur->firstMem;
471			break;
472		case PFMEM:
473			if (bus_cur->firstPFMem)
474				res = bus_cur->firstPFMem;
475			break;
476		case IO:
477			if (bus_cur->firstIO)
478				res = bus_cur->firstIO;
479			break;
480	}
481
482	if (res) {
483		while (res) {
484			if (res->rangeno == rangeno)
485				break;
486			if (res->next)
487				res = res->next;
488			else if (res->nextRange)
489				res = res->nextRange;
490			else {
491				eol = 1;
492				break;
493			}
494		}
495
496		if (!eol) {
497			/* found the range */
498			while (res) {
499				++res->rangeno;
500				res = res->next;
501			}
502		}
503	}
504}
505
506static void fix_me (struct resource_node *res, struct bus_node *bus_cur, struct range_node *range)
507{
508	char * str = "";
509	switch (res->type) {
510		case IO:
511			str = "io";
512			break;
513		case MEM:
514			str = "mem";
515			break;
516		case PFMEM:
517			str = "pfmem";
518			break;
519	}
520
521	while (res) {
522		if (res->rangeno == -1) {
523			while (range) {
524				if ((res->start >= range->start) && (res->end <= range->end)) {
525					res->rangeno = range->rangeno;
526					debug ("%s->rangeno in fix_resources is %d\n", str, res->rangeno);
527					switch (res->type) {
528						case IO:
529							--bus_cur->needIOUpdate;
530							break;
531						case MEM:
532							--bus_cur->needMemUpdate;
533							break;
534						case PFMEM:
535							--bus_cur->needPFMemUpdate;
536							break;
537					}
538					break;
539				}
540				range = range->next;
541			}
542		}
543		if (res->next)
544			res = res->next;
545		else
546			res = res->nextRange;
547	}
548
549}
550
551/*****************************************************************************
552 * This routine reassigns the range numbers to the resources that had a -1
553 * This case can happen only if upon initialization, resources taken by pci dev
554 * appear in EBDA before the resources allocated for that bus, since we don't
555 * know the range, we assign -1, and this routine is called after a new range
556 * is assigned to see the resources with unknown range belong to the added range
557 *
558 * Input: current bus
559 * Output: none, list of resources for that bus are fixed if can be
560 *******************************************************************************/
561static void fix_resources (struct bus_node *bus_cur)
562{
563	struct range_node *range;
564	struct resource_node *res;
565
566	debug ("%s - bus_cur->busno = %d\n", __func__, bus_cur->busno);
567
568	if (bus_cur->needIOUpdate) {
569		res = bus_cur->firstIO;
570		range = bus_cur->rangeIO;
571		fix_me (res, bus_cur, range);
572	}
573	if (bus_cur->needMemUpdate) {
574		res = bus_cur->firstMem;
575		range = bus_cur->rangeMem;
576		fix_me (res, bus_cur, range);
577	}
578	if (bus_cur->needPFMemUpdate) {
579		res = bus_cur->firstPFMem;
580		range = bus_cur->rangePFMem;
581		fix_me (res, bus_cur, range);
582	}
583}
584
585/*******************************************************************************
586 * This routine adds a resource to the list of resources to the appropriate bus
587 * based on their resource type and sorted by their starting addresses.  It assigns
588 * the ptrs to next and nextRange if needed.
589 *
590 * Input: resource ptr
591 * Output: ptrs assigned (to the node)
592 * 0 or -1
593 *******************************************************************************/
594int ibmphp_add_resource (struct resource_node *res)
595{
596	struct resource_node *res_cur;
597	struct resource_node *res_prev;
598	struct bus_node *bus_cur;
599	struct range_node *range_cur = NULL;
600	struct resource_node *res_start = NULL;
601
602	debug ("%s - enter\n", __func__);
603
604	if (!res) {
605		err ("NULL passed to add\n");
606		return -ENODEV;
607	}
608
609	bus_cur = find_bus_wprev (res->busno, NULL, 0);
610
611	if (!bus_cur) {
612		/* didn't find a bus, smth's wrong!!! */
613		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
614		return -ENODEV;
615	}
616
617	/* Normal case */
618	switch (res->type) {
619		case IO:
620			range_cur = bus_cur->rangeIO;
621			res_start = bus_cur->firstIO;
622			break;
623		case MEM:
624			range_cur = bus_cur->rangeMem;
625			res_start = bus_cur->firstMem;
626			break;
627		case PFMEM:
628			range_cur = bus_cur->rangePFMem;
629			res_start = bus_cur->firstPFMem;
630			break;
631		default:
632			err ("cannot read the type of the resource to add... problem\n");
633			return -EINVAL;
634	}
635	while (range_cur) {
636		if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
637			res->rangeno = range_cur->rangeno;
638			break;
639		}
640		range_cur = range_cur->next;
641	}
642
643	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644	 * this is again the case of rangeno = -1
645	 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
646	 */
647
648	if (!range_cur) {
649		switch (res->type) {
650			case IO:
651				++bus_cur->needIOUpdate;
652				break;
653			case MEM:
654				++bus_cur->needMemUpdate;
655				break;
656			case PFMEM:
657				++bus_cur->needPFMemUpdate;
658				break;
659		}
660		res->rangeno = -1;
661	}
662
663	debug ("The range is %d\n", res->rangeno);
664	if (!res_start) {
665		/* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
666		switch (res->type) {
667			case IO:
668				bus_cur->firstIO = res;
669				break;
670			case MEM:
671				bus_cur->firstMem = res;
672				break;
673			case PFMEM:
674				bus_cur->firstPFMem = res;
675				break;
676		}
677		res->next = NULL;
678		res->nextRange = NULL;
679	} else {
680		res_cur = res_start;
681		res_prev = NULL;
682
683		debug ("res_cur->rangeno is %d\n", res_cur->rangeno);
684
685		while (res_cur) {
686			if (res_cur->rangeno >= res->rangeno)
687				break;
688			res_prev = res_cur;
689			if (res_cur->next)
690				res_cur = res_cur->next;
691			else
692				res_cur = res_cur->nextRange;
693		}
694
695		if (!res_cur) {
696			/* at the end of the resource list */
697			debug ("i should be here, [%x - %x]\n", res->start, res->end);
698			res_prev->nextRange = res;
699			res->next = NULL;
700			res->nextRange = NULL;
701		} else if (res_cur->rangeno == res->rangeno) {
702			/* in the same range */
703			while (res_cur) {
704				if (res->start < res_cur->start)
705					break;
706				res_prev = res_cur;
707				res_cur = res_cur->next;
708			}
709			if (!res_cur) {
710				/* the last resource in this range */
711				res_prev->next = res;
712				res->next = NULL;
713				res->nextRange = res_prev->nextRange;
714				res_prev->nextRange = NULL;
715			} else if (res->start < res_cur->start) {
716				/* at the beginning or middle of the range */
717				if (!res_prev)	{
718					switch (res->type) {
719						case IO:
720							bus_cur->firstIO = res;
721							break;
722						case MEM:
723							bus_cur->firstMem = res;
724							break;
725						case PFMEM:
726							bus_cur->firstPFMem = res;
727							break;
728					}
729				} else if (res_prev->rangeno == res_cur->rangeno)
730					res_prev->next = res;
731				else
732					res_prev->nextRange = res;
733
734				res->next = res_cur;
735				res->nextRange = NULL;
736			}
737		} else {
738			/* this is the case where it is 1st occurrence of the range */
739			if (!res_prev) {
740				/* at the beginning of the resource list */
741				res->next = NULL;
742				switch (res->type) {
743					case IO:
744						res->nextRange = bus_cur->firstIO;
745						bus_cur->firstIO = res;
746						break;
747					case MEM:
748						res->nextRange = bus_cur->firstMem;
749						bus_cur->firstMem = res;
750						break;
751					case PFMEM:
752						res->nextRange = bus_cur->firstPFMem;
753						bus_cur->firstPFMem = res;
754						break;
755				}
756			} else if (res_cur->rangeno > res->rangeno) {
757				/* in the middle of the resource list */
758				res_prev->nextRange = res;
759				res->next = NULL;
760				res->nextRange = res_cur;
761			}
762		}
763	}
764
765	debug ("%s - exit\n", __func__);
766	return 0;
767}
768
769/****************************************************************************
770 * This routine will remove the resource from the list of resources
771 *
772 * Input: io, mem, and/or pfmem resource to be deleted
773 * Ouput: modified resource list
774 *        0 or error code
775 ****************************************************************************/
776int ibmphp_remove_resource (struct resource_node *res)
777{
778	struct bus_node *bus_cur;
779	struct resource_node *res_cur = NULL;
780	struct resource_node *res_prev;
781	struct resource_node *mem_cur;
782	char * type = "";
783
784	if (!res)  {
785		err ("resource to remove is NULL\n");
786		return -ENODEV;
787	}
788
789	bus_cur = find_bus_wprev (res->busno, NULL, 0);
790
791	if (!bus_cur) {
792		err ("cannot find corresponding bus of the io resource to remove  "
793			"bailing out...\n");
794		return -ENODEV;
795	}
796
797	switch (res->type) {
798		case IO:
799			res_cur = bus_cur->firstIO;
800			type = "io";
801			break;
802		case MEM:
803			res_cur = bus_cur->firstMem;
804			type = "mem";
805			break;
806		case PFMEM:
807			res_cur = bus_cur->firstPFMem;
808			type = "pfmem";
809			break;
810		default:
811			err ("unknown type for resource to remove\n");
812			return -EINVAL;
813	}
814	res_prev = NULL;
815
816	while (res_cur) {
817		if ((res_cur->start == res->start) && (res_cur->end == res->end))
818			break;
819		res_prev = res_cur;
820		if (res_cur->next)
821			res_cur = res_cur->next;
822		else
823			res_cur = res_cur->nextRange;
824	}
825
826	if (!res_cur) {
827		if (res->type == PFMEM) {
828			/*
829			 * case where pfmem might be in the PFMemFromMem list
830			 * so will also need to remove the corresponding mem
831			 * entry
832			 */
833			res_cur = bus_cur->firstPFMemFromMem;
834			res_prev = NULL;
835
836			while (res_cur) {
837				if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
838					mem_cur = bus_cur->firstMem;
839					while (mem_cur) {
840						if ((mem_cur->start == res_cur->start)
841						    && (mem_cur->end == res_cur->end))
842							break;
843						if (mem_cur->next)
844							mem_cur = mem_cur->next;
845						else
846							mem_cur = mem_cur->nextRange;
847					}
848					if (!mem_cur) {
849						err ("cannot find corresponding mem node for pfmem...\n");
850						return -EINVAL;
851					}
852
853					ibmphp_remove_resource (mem_cur);
854					if (!res_prev)
855						bus_cur->firstPFMemFromMem = res_cur->next;
856					else
857						res_prev->next = res_cur->next;
858					kfree (res_cur);
859					return 0;
860				}
861				res_prev = res_cur;
862				if (res_cur->next)
863					res_cur = res_cur->next;
864				else
865					res_cur = res_cur->nextRange;
866			}
867			if (!res_cur) {
868				err ("cannot find pfmem to delete...\n");
869				return -EINVAL;
870			}
871		} else {
872			err ("the %s resource is not in the list to be deleted...\n", type);
873			return -EINVAL;
874		}
875	}
876	if (!res_prev) {
877		/* first device to be deleted */
878		if (res_cur->next) {
879			switch (res->type) {
880				case IO:
881					bus_cur->firstIO = res_cur->next;
882					break;
883				case MEM:
884					bus_cur->firstMem = res_cur->next;
885					break;
886				case PFMEM:
887					bus_cur->firstPFMem = res_cur->next;
888					break;
889			}
890		} else if (res_cur->nextRange) {
891			switch (res->type) {
892				case IO:
893					bus_cur->firstIO = res_cur->nextRange;
894					break;
895				case MEM:
896					bus_cur->firstMem = res_cur->nextRange;
897					break;
898				case PFMEM:
899					bus_cur->firstPFMem = res_cur->nextRange;
900					break;
901			}
902		} else {
903			switch (res->type) {
904				case IO:
905					bus_cur->firstIO = NULL;
906					break;
907				case MEM:
908					bus_cur->firstMem = NULL;
909					break;
910				case PFMEM:
911					bus_cur->firstPFMem = NULL;
912					break;
913			}
914		}
915		kfree (res_cur);
916		return 0;
917	} else {
918		if (res_cur->next) {
919			if (res_prev->rangeno == res_cur->rangeno)
920				res_prev->next = res_cur->next;
921			else
922				res_prev->nextRange = res_cur->next;
923		} else if (res_cur->nextRange) {
924			res_prev->next = NULL;
925			res_prev->nextRange = res_cur->nextRange;
926		} else {
927			res_prev->next = NULL;
928			res_prev->nextRange = NULL;
929		}
930		kfree (res_cur);
931		return 0;
932	}
933
934	return 0;
935}
936
937static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res)
938{
939	struct range_node * range = NULL;
940
941	switch (res->type) {
942		case IO:
943			range = bus_cur->rangeIO;
944			break;
945		case MEM:
946			range = bus_cur->rangeMem;
947			break;
948		case PFMEM:
949			range = bus_cur->rangePFMem;
950			break;
951		default:
952			err ("cannot read resource type in find_range\n");
953	}
954
955	while (range) {
956		if (res->rangeno == range->rangeno)
957			break;
958		range = range->next;
959	}
960	return range;
961}
962
963/*****************************************************************************
964 * This routine will check to make sure the io/mem/pfmem->len that the device asked for
965 * can fit w/i our list of available IO/MEM/PFMEM resources.  If cannot, returns -EINVAL,
966 * otherwise, returns 0
967 *
968 * Input: resource
969 * Ouput: the correct start and end address are inputted into the resource node,
970 *        0 or -EINVAL
971 *****************************************************************************/
972int ibmphp_check_resource (struct resource_node *res, u8 bridge)
973{
974	struct bus_node *bus_cur;
975	struct range_node *range = NULL;
976	struct resource_node *res_prev;
977	struct resource_node *res_cur = NULL;
978	u32 len_cur = 0, start_cur = 0, len_tmp = 0;
979	int noranges = 0;
980	u32 tmp_start;		/* this is to make sure start address is divisible by the length needed */
981	u32 tmp_divide;
982	u8 flag = 0;
983
984	if (!res)
985		return -EINVAL;
986
987	if (bridge) {
988		/* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/
989		if (res->type == IO)
990			tmp_divide = IOBRIDGE;
991		else
992			tmp_divide = MEMBRIDGE;
993	} else
994		tmp_divide = res->len;
995
996	bus_cur = find_bus_wprev (res->busno, NULL, 0);
997
998	if (!bus_cur) {
999		/* didn't find a bus, smth's wrong!!! */
1000		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
1001		return -EINVAL;
1002	}
1003
1004	debug ("%s - enter\n", __func__);
1005	debug ("bus_cur->busno is %d\n", bus_cur->busno);
1006
1007	/* This is a quick fix to not mess up with the code very much.  i.e.,
1008	 * 2000-2fff, len = 1000, but when we compare, we need it to be fff */
1009	res->len -= 1;
1010
1011	switch (res->type) {
1012		case IO:
1013			res_cur = bus_cur->firstIO;
1014			noranges = bus_cur->noIORanges;
1015			break;
1016		case MEM:
1017			res_cur = bus_cur->firstMem;
1018			noranges = bus_cur->noMemRanges;
1019			break;
1020		case PFMEM:
1021			res_cur = bus_cur->firstPFMem;
1022			noranges = bus_cur->noPFMemRanges;
1023			break;
1024		default:
1025			err ("wrong type of resource to check\n");
1026			return -EINVAL;
1027	}
1028	res_prev = NULL;
1029
1030	while (res_cur) {
1031		range = find_range (bus_cur, res_cur);
1032		debug ("%s - rangeno = %d\n", __func__, res_cur->rangeno);
1033
1034		if (!range) {
1035			err ("no range for the device exists... bailing out...\n");
1036			return -EINVAL;
1037		}
1038
1039		/* found our range */
1040		if (!res_prev) {
1041			/* first time in the loop */
1042			if ((res_cur->start != range->start) && ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
1043				debug ("len_tmp = %x\n", len_tmp);
1044
1045				if ((len_tmp < len_cur) || (len_cur == 0)) {
1046
1047					if ((range->start % tmp_divide) == 0) {
1048						/* just perfect, starting address is divisible by length */
1049						flag = 1;
1050						len_cur = len_tmp;
1051						start_cur = range->start;
1052					} else {
1053						/* Needs adjusting */
1054						tmp_start = range->start;
1055						flag = 0;
1056
1057						while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
1058							if ((tmp_start % tmp_divide) == 0) {
1059								flag = 1;
1060								len_cur = len_tmp;
1061								start_cur = tmp_start;
1062								break;
1063							}
1064							tmp_start += tmp_divide - tmp_start % tmp_divide;
1065							if (tmp_start >= res_cur->start - 1)
1066								break;
1067						}
1068					}
1069
1070					if (flag && len_cur == res->len) {
1071						debug ("but we are not here, right?\n");
1072						res->start = start_cur;
1073						res->len += 1; /* To restore the balance */
1074						res->end = res->start + res->len - 1;
1075						return 0;
1076					}
1077				}
1078			}
1079		}
1080		if (!res_cur->next) {
1081			/* last device on the range */
1082			if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) {
1083				debug ("len_tmp = %x\n", len_tmp);
1084				if ((len_tmp < len_cur) || (len_cur == 0)) {
1085
1086					if (((res_cur->end + 1) % tmp_divide) == 0) {
1087						/* just perfect, starting address is divisible by length */
1088						flag = 1;
1089						len_cur = len_tmp;
1090						start_cur = res_cur->end + 1;
1091					} else {
1092						/* Needs adjusting */
1093						tmp_start = res_cur->end + 1;
1094						flag = 0;
1095
1096						while ((len_tmp = range->end - tmp_start) >= res->len) {
1097							if ((tmp_start % tmp_divide) == 0) {
1098								flag = 1;
1099								len_cur = len_tmp;
1100								start_cur = tmp_start;
1101								break;
1102							}
1103							tmp_start += tmp_divide - tmp_start % tmp_divide;
1104							if (tmp_start >= range->end)
1105								break;
1106						}
1107					}
1108					if (flag && len_cur == res->len) {
1109						res->start = start_cur;
1110						res->len += 1; /* To restore the balance */
1111						res->end = res->start + res->len - 1;
1112						return 0;
1113					}
1114				}
1115			}
1116		}
1117
1118		if (res_prev) {
1119			if (res_prev->rangeno != res_cur->rangeno) {
1120				/* 1st device on this range */
1121				if ((res_cur->start != range->start) &&
1122					((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
1123					if ((len_tmp < len_cur) || (len_cur == 0)) {
1124						if ((range->start % tmp_divide) == 0) {
1125							/* just perfect, starting address is divisible by length */
1126							flag = 1;
1127							len_cur = len_tmp;
1128							start_cur = range->start;
1129						} else {
1130							/* Needs adjusting */
1131							tmp_start = range->start;
1132							flag = 0;
1133
1134							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
1135								if ((tmp_start % tmp_divide) == 0) {
1136									flag = 1;
1137									len_cur = len_tmp;
1138									start_cur = tmp_start;
1139									break;
1140								}
1141								tmp_start += tmp_divide - tmp_start % tmp_divide;
1142								if (tmp_start >= res_cur->start - 1)
1143									break;
1144							}
1145						}
1146
1147						if (flag && len_cur == res->len) {
1148							res->start = start_cur;
1149							res->len += 1; /* To restore the balance */
1150							res->end = res->start + res->len - 1;
1151							return 0;
1152						}
1153					}
1154				}
1155			} else {
1156				/* in the same range */
1157				if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) {
1158					if ((len_tmp < len_cur) || (len_cur == 0)) {
1159						if (((res_prev->end + 1) % tmp_divide) == 0) {
1160							/* just perfect, starting address's divisible by length */
1161							flag = 1;
1162							len_cur = len_tmp;
1163							start_cur = res_prev->end + 1;
1164						} else {
1165							/* Needs adjusting */
1166							tmp_start = res_prev->end + 1;
1167							flag = 0;
1168
1169							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
1170								if ((tmp_start % tmp_divide) == 0) {
1171									flag = 1;
1172									len_cur = len_tmp;
1173									start_cur = tmp_start;
1174									break;
1175								}
1176								tmp_start += tmp_divide - tmp_start % tmp_divide;
1177								if (tmp_start >= res_cur->start - 1)
1178									break;
1179							}
1180						}
1181
1182						if (flag && len_cur == res->len) {
1183							res->start = start_cur;
1184							res->len += 1; /* To restore the balance */
1185							res->end = res->start + res->len - 1;
1186							return 0;
1187						}
1188					}
1189				}
1190			}
1191		}
1192		/* end if (res_prev) */
1193		res_prev = res_cur;
1194		if (res_cur->next)
1195			res_cur = res_cur->next;
1196		else
1197			res_cur = res_cur->nextRange;
1198	}	/* end of while */
1199
1200
1201	if (!res_prev) {
1202		/* 1st device ever */
1203		/* need to find appropriate range */
1204		switch (res->type) {
1205			case IO:
1206				range = bus_cur->rangeIO;
1207				break;
1208			case MEM:
1209				range = bus_cur->rangeMem;
1210				break;
1211			case PFMEM:
1212				range = bus_cur->rangePFMem;
1213				break;
1214		}
1215		while (range) {
1216			if ((len_tmp = range->end - range->start) >= res->len) {
1217				if ((len_tmp < len_cur) || (len_cur == 0)) {
1218					if ((range->start % tmp_divide) == 0) {
1219						/* just perfect, starting address's divisible by length */
1220						flag = 1;
1221						len_cur = len_tmp;
1222						start_cur = range->start;
1223					} else {
1224						/* Needs adjusting */
1225						tmp_start = range->start;
1226						flag = 0;
1227
1228						while ((len_tmp = range->end - tmp_start) >= res->len) {
1229							if ((tmp_start % tmp_divide) == 0) {
1230								flag = 1;
1231								len_cur = len_tmp;
1232								start_cur = tmp_start;
1233								break;
1234							}
1235							tmp_start += tmp_divide - tmp_start % tmp_divide;
1236							if (tmp_start >= range->end)
1237								break;
1238						}
1239					}
1240
1241					if (flag && len_cur == res->len) {
1242						res->start = start_cur;
1243						res->len += 1; /* To restore the balance */
1244						res->end = res->start + res->len - 1;
1245						return 0;
1246					}
1247				}
1248			}
1249			range = range->next;
1250		}		/* end of while */
1251
1252		if ((!range) && (len_cur == 0)) {
1253			/* have gone through the list of devices and ranges and haven't found n.e.thing */
1254			err ("no appropriate range.. bailing out...\n");
1255			return -EINVAL;
1256		} else if (len_cur) {
1257			res->start = start_cur;
1258			res->len += 1; /* To restore the balance */
1259			res->end = res->start + res->len - 1;
1260			return 0;
1261		}
1262	}
1263
1264	if (!res_cur) {
1265		debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);
1266		if (res_prev->rangeno < noranges) {
1267			/* if there're more ranges out there to check */
1268			switch (res->type) {
1269				case IO:
1270					range = bus_cur->rangeIO;
1271					break;
1272				case MEM:
1273					range = bus_cur->rangeMem;
1274					break;
1275				case PFMEM:
1276					range = bus_cur->rangePFMem;
1277					break;
1278			}
1279			while (range) {
1280				if ((len_tmp = range->end - range->start) >= res->len) {
1281					if ((len_tmp < len_cur) || (len_cur == 0)) {
1282						if ((range->start % tmp_divide) == 0) {
1283							/* just perfect, starting address's divisible by length */
1284							flag = 1;
1285							len_cur = len_tmp;
1286							start_cur = range->start;
1287						} else {
1288							/* Needs adjusting */
1289							tmp_start = range->start;
1290							flag = 0;
1291
1292							while ((len_tmp = range->end - tmp_start) >= res->len) {
1293								if ((tmp_start % tmp_divide) == 0) {
1294									flag = 1;
1295									len_cur = len_tmp;
1296									start_cur = tmp_start;
1297									break;
1298								}
1299								tmp_start += tmp_divide - tmp_start % tmp_divide;
1300								if (tmp_start >= range->end)
1301									break;
1302							}
1303						}
1304
1305						if (flag && len_cur == res->len) {
1306							res->start = start_cur;
1307							res->len += 1; /* To restore the balance */
1308							res->end = res->start + res->len - 1;
1309							return 0;
1310						}
1311					}
1312				}
1313				range = range->next;
1314			}	/* end of while */
1315
1316			if ((!range) && (len_cur == 0)) {
1317				/* have gone through the list of devices and ranges and haven't found n.e.thing */
1318				err ("no appropriate range.. bailing out...\n");
1319				return -EINVAL;
1320			} else if (len_cur) {
1321				res->start = start_cur;
1322				res->len += 1; /* To restore the balance */
1323				res->end = res->start + res->len - 1;
1324				return 0;
1325			}
1326		} else {
1327			/* no more ranges to check on */
1328			if (len_cur) {
1329				res->start = start_cur;
1330				res->len += 1; /* To restore the balance */
1331				res->end = res->start + res->len - 1;
1332				return 0;
1333			} else {
1334				/* have gone through the list of devices and haven't found n.e.thing */
1335				err ("no appropriate range.. bailing out...\n");
1336				return -EINVAL;
1337			}
1338		}
1339	}	/* end if(!res_cur) */
1340	return -EINVAL;
1341}
1342
1343/********************************************************************************
1344 * This routine is called from remove_card if the card contained PPB.
1345 * It will remove all the resources on the bus as well as the bus itself
1346 * Input: Bus
1347 * Ouput: 0, -ENODEV
1348 ********************************************************************************/
1349int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)
1350{
1351	struct resource_node *res_cur;
1352	struct resource_node *res_tmp;
1353	struct bus_node *prev_bus;
1354	int rc;
1355
1356	prev_bus = find_bus_wprev (parent_busno, NULL, 0);
1357
1358	if (!prev_bus) {
1359		debug ("something terribly wrong. Cannot find parent bus to the one to remove\n");
1360		return -ENODEV;
1361	}
1362
1363	debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);
1364
1365	rc = remove_ranges (bus, prev_bus);
1366	if (rc)
1367		return rc;
1368
1369	if (bus->firstIO) {
1370		res_cur = bus->firstIO;
1371		while (res_cur) {
1372			res_tmp = res_cur;
1373			if (res_cur->next)
1374				res_cur = res_cur->next;
1375			else
1376				res_cur = res_cur->nextRange;
1377			kfree (res_tmp);
1378			res_tmp = NULL;
1379		}
1380		bus->firstIO = NULL;
1381	}
1382	if (bus->firstMem) {
1383		res_cur = bus->firstMem;
1384		while (res_cur) {
1385			res_tmp = res_cur;
1386			if (res_cur->next)
1387				res_cur = res_cur->next;
1388			else
1389				res_cur = res_cur->nextRange;
1390			kfree (res_tmp);
1391			res_tmp = NULL;
1392		}
1393		bus->firstMem = NULL;
1394	}
1395	if (bus->firstPFMem) {
1396		res_cur = bus->firstPFMem;
1397		while (res_cur) {
1398			res_tmp = res_cur;
1399			if (res_cur->next)
1400				res_cur = res_cur->next;
1401			else
1402				res_cur = res_cur->nextRange;
1403			kfree (res_tmp);
1404			res_tmp = NULL;
1405		}
1406		bus->firstPFMem = NULL;
1407	}
1408
1409	if (bus->firstPFMemFromMem) {
1410		res_cur = bus->firstPFMemFromMem;
1411		while (res_cur) {
1412			res_tmp = res_cur;
1413			res_cur = res_cur->next;
1414
1415			kfree (res_tmp);
1416			res_tmp = NULL;
1417		}
1418		bus->firstPFMemFromMem = NULL;
1419	}
1420
1421	list_del (&bus->bus_list);
1422	kfree (bus);
1423	return 0;
1424}
1425
1426/******************************************************************************
1427 * This routine deletes the ranges from a given bus, and the entries from the
1428 * parent's bus in the resources
1429 * Input: current bus, previous bus
1430 * Output: 0, -EINVAL
1431 ******************************************************************************/
1432static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)
1433{
1434	struct range_node *range_cur;
1435	struct range_node *range_tmp;
1436	int i;
1437	struct resource_node *res = NULL;
1438
1439	if (bus_cur->noIORanges) {
1440		range_cur = bus_cur->rangeIO;
1441		for (i = 0; i < bus_cur->noIORanges; i++) {
1442			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0)
1443				return -EINVAL;
1444			ibmphp_remove_resource (res);
1445
1446			range_tmp = range_cur;
1447			range_cur = range_cur->next;
1448			kfree (range_tmp);
1449			range_tmp = NULL;
1450		}
1451		bus_cur->rangeIO = NULL;
1452	}
1453	if (bus_cur->noMemRanges) {
1454		range_cur = bus_cur->rangeMem;
1455		for (i = 0; i < bus_cur->noMemRanges; i++) {
1456			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0)
1457				return -EINVAL;
1458
1459			ibmphp_remove_resource (res);
1460			range_tmp = range_cur;
1461			range_cur = range_cur->next;
1462			kfree (range_tmp);
1463			range_tmp = NULL;
1464		}
1465		bus_cur->rangeMem = NULL;
1466	}
1467	if (bus_cur->noPFMemRanges) {
1468		range_cur = bus_cur->rangePFMem;
1469		for (i = 0; i < bus_cur->noPFMemRanges; i++) {
1470			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0)
1471				return -EINVAL;
1472
1473			ibmphp_remove_resource (res);
1474			range_tmp = range_cur;
1475			range_cur = range_cur->next;
1476			kfree (range_tmp);
1477			range_tmp = NULL;
1478		}
1479		bus_cur->rangePFMem = NULL;
1480	}
1481	return 0;
1482}
1483
1484/*
1485 * find the resource node in the bus
1486 * Input: Resource needed, start address of the resource, type of resource
1487 */
1488int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag)
1489{
1490	struct resource_node *res_cur = NULL;
1491	char * type = "";
1492
1493	if (!bus) {
1494		err ("The bus passed in NULL to find resource\n");
1495		return -ENODEV;
1496	}
1497
1498	switch (flag) {
1499		case IO:
1500			res_cur = bus->firstIO;
1501			type = "io";
1502			break;
1503		case MEM:
1504			res_cur = bus->firstMem;
1505			type = "mem";
1506			break;
1507		case PFMEM:
1508			res_cur = bus->firstPFMem;
1509			type = "pfmem";
1510			break;
1511		default:
1512			err ("wrong type of flag\n");
1513			return -EINVAL;
1514	}
1515
1516	while (res_cur) {
1517		if (res_cur->start == start_address) {
1518			*res = res_cur;
1519			break;
1520		}
1521		if (res_cur->next)
1522			res_cur = res_cur->next;
1523		else
1524			res_cur = res_cur->nextRange;
1525	}
1526
1527	if (!res_cur) {
1528		if (flag == PFMEM) {
1529			res_cur = bus->firstPFMemFromMem;
1530			while (res_cur) {
1531				if (res_cur->start == start_address) {
1532					*res = res_cur;
1533					break;
1534				}
1535				res_cur = res_cur->next;
1536			}
1537			if (!res_cur) {
1538				debug ("SOS...cannot find %s resource in the bus.\n", type);
1539				return -EINVAL;
1540			}
1541		} else {
1542			debug ("SOS... cannot find %s resource in the bus.\n", type);
1543			return -EINVAL;
1544		}
1545	}
1546
1547	if (*res)
1548		debug ("*res->start = %x\n", (*res)->start);
1549
1550	return 0;
1551}
1552
1553/***********************************************************************
1554 * This routine will free the resource structures used by the
1555 * system.  It is called from cleanup routine for the module
1556 * Parameters: none
1557 * Returns: none
1558 ***********************************************************************/
1559void ibmphp_free_resources (void)
1560{
1561	struct bus_node *bus_cur = NULL;
1562	struct bus_node *bus_tmp;
1563	struct range_node *range_cur;
1564	struct range_node *range_tmp;
1565	struct resource_node *res_cur;
1566	struct resource_node *res_tmp;
1567	struct list_head *tmp;
1568	struct list_head *next;
1569	int i = 0;
1570	flags = 1;
1571
1572	list_for_each_safe (tmp, next, &gbuses) {
1573		bus_cur = list_entry (tmp, struct bus_node, bus_list);
1574		if (bus_cur->noIORanges) {
1575			range_cur = bus_cur->rangeIO;
1576			for (i = 0; i < bus_cur->noIORanges; i++) {
1577				if (!range_cur)
1578					break;
1579				range_tmp = range_cur;
1580				range_cur = range_cur->next;
1581				kfree (range_tmp);
1582				range_tmp = NULL;
1583			}
1584		}
1585		if (bus_cur->noMemRanges) {
1586			range_cur = bus_cur->rangeMem;
1587			for (i = 0; i < bus_cur->noMemRanges; i++) {
1588				if (!range_cur)
1589					break;
1590				range_tmp = range_cur;
1591				range_cur = range_cur->next;
1592				kfree (range_tmp);
1593				range_tmp = NULL;
1594			}
1595		}
1596		if (bus_cur->noPFMemRanges) {
1597			range_cur = bus_cur->rangePFMem;
1598			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
1599				if (!range_cur)
1600					break;
1601				range_tmp = range_cur;
1602				range_cur = range_cur->next;
1603				kfree (range_tmp);
1604				range_tmp = NULL;
1605			}
1606		}
1607
1608		if (bus_cur->firstIO) {
1609			res_cur = bus_cur->firstIO;
1610			while (res_cur) {
1611				res_tmp = res_cur;
1612				if (res_cur->next)
1613					res_cur = res_cur->next;
1614				else
1615					res_cur = res_cur->nextRange;
1616				kfree (res_tmp);
1617				res_tmp = NULL;
1618			}
1619			bus_cur->firstIO = NULL;
1620		}
1621		if (bus_cur->firstMem) {
1622			res_cur = bus_cur->firstMem;
1623			while (res_cur) {
1624				res_tmp = res_cur;
1625				if (res_cur->next)
1626					res_cur = res_cur->next;
1627				else
1628					res_cur = res_cur->nextRange;
1629				kfree (res_tmp);
1630				res_tmp = NULL;
1631			}
1632			bus_cur->firstMem = NULL;
1633		}
1634		if (bus_cur->firstPFMem) {
1635			res_cur = bus_cur->firstPFMem;
1636			while (res_cur) {
1637				res_tmp = res_cur;
1638				if (res_cur->next)
1639					res_cur = res_cur->next;
1640				else
1641					res_cur = res_cur->nextRange;
1642				kfree (res_tmp);
1643				res_tmp = NULL;
1644			}
1645			bus_cur->firstPFMem = NULL;
1646		}
1647
1648		if (bus_cur->firstPFMemFromMem) {
1649			res_cur = bus_cur->firstPFMemFromMem;
1650			while (res_cur) {
1651				res_tmp = res_cur;
1652				res_cur = res_cur->next;
1653
1654				kfree (res_tmp);
1655				res_tmp = NULL;
1656			}
1657			bus_cur->firstPFMemFromMem = NULL;
1658		}
1659
1660		bus_tmp = bus_cur;
1661		list_del (&bus_cur->bus_list);
1662		kfree (bus_tmp);
1663		bus_tmp = NULL;
1664	}
1665}
1666
1667/*********************************************************************************
1668 * This function will go over the PFmem resources to check if the EBDA allocated
1669 * pfmem out of memory buckets of the bus.  If so, it will change the range numbers
1670 * and a flag to indicate that this resource is out of memory. It will also move the
1671 * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create
1672 * a new Mem node
1673 * This routine is called right after initialization
1674 *******************************************************************************/
1675static int __init once_over (void)
1676{
1677	struct resource_node *pfmem_cur;
1678	struct resource_node *pfmem_prev;
1679	struct resource_node *mem;
1680	struct bus_node *bus_cur;
1681	struct list_head *tmp;
1682
1683	list_for_each (tmp, &gbuses) {
1684		bus_cur = list_entry (tmp, struct bus_node, bus_list);
1685		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
1686			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
1687				pfmem_cur->fromMem = 1;
1688				if (pfmem_prev)
1689					pfmem_prev->next = pfmem_cur->next;
1690				else
1691					bus_cur->firstPFMem = pfmem_cur->next;
1692
1693				if (!bus_cur->firstPFMemFromMem)
1694					pfmem_cur->next = NULL;
1695				else
1696					/* we don't need to sort PFMemFromMem since we're using mem node for
1697					   all the real work anyways, so just insert at the beginning of the
1698					   list
1699					 */
1700					pfmem_cur->next = bus_cur->firstPFMemFromMem;
1701
1702				bus_cur->firstPFMemFromMem = pfmem_cur;
1703
1704				mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
1705				if (!mem) {
1706					err ("out of system memory\n");
1707					return -ENOMEM;
1708				}
1709				mem->type = MEM;
1710				mem->busno = pfmem_cur->busno;
1711				mem->devfunc = pfmem_cur->devfunc;
1712				mem->start = pfmem_cur->start;
1713				mem->end = pfmem_cur->end;
1714				mem->len = pfmem_cur->len;
1715				if (ibmphp_add_resource (mem) < 0)
1716					err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");
1717				pfmem_cur->rangeno = mem->rangeno;
1718			}	/* end for pfmem */
1719		}	/* end if */
1720	}	/* end list_for_each bus */
1721	return 0;
1722}
1723
1724int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem)
1725{
1726	struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0);
1727
1728	if (!bus_cur) {
1729		err ("cannot find bus of pfmem to add...\n");
1730		return -ENODEV;
1731	}
1732
1733	if (bus_cur->firstPFMemFromMem)
1734		pfmem->next = bus_cur->firstPFMemFromMem;
1735	else
1736		pfmem->next = NULL;
1737
1738	bus_cur->firstPFMemFromMem = pfmem;
1739
1740	return 0;
1741}
1742
1743/* This routine just goes through the buses to see if the bus already exists.
1744 * It is called from ibmphp_find_sec_number, to find out a secondary bus number for
1745 * bridged cards
1746 * Parameters: bus_number
1747 * Returns: Bus pointer or NULL
1748 */
1749struct bus_node *ibmphp_find_res_bus (u8 bus_number)
1750{
1751	return find_bus_wprev (bus_number, NULL, 0);
1752}
1753
1754static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
1755{
1756	struct bus_node *bus_cur;
1757	struct list_head *tmp;
1758	struct list_head *tmp_prev;
1759
1760	list_for_each (tmp, &gbuses) {
1761		tmp_prev = tmp->prev;
1762		bus_cur = list_entry (tmp, struct bus_node, bus_list);
1763		if (flag)
1764			*prev = list_entry (tmp_prev, struct bus_node, bus_list);
1765		if (bus_cur->busno == bus_number)
1766			return bus_cur;
1767	}
1768
1769	return NULL;
1770}
1771
1772void ibmphp_print_test (void)
1773{
1774	int i = 0;
1775	struct bus_node *bus_cur = NULL;
1776	struct range_node *range;
1777	struct resource_node *res;
1778	struct list_head *tmp;
1779
1780	debug_pci ("*****************START**********************\n");
1781
1782	if ((!list_empty(&gbuses)) && flags) {
1783		err ("The GBUSES is not NULL?!?!?!?!?\n");
1784		return;
1785	}
1786
1787	list_for_each (tmp, &gbuses) {
1788		bus_cur = list_entry (tmp, struct bus_node, bus_list);
1789		debug_pci ("This is bus # %d.  There are\n", bus_cur->busno);
1790		debug_pci ("IORanges = %d\t", bus_cur->noIORanges);
1791		debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);
1792		debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);
1793		debug_pci ("The IO Ranges are as follows:\n");
1794		if (bus_cur->rangeIO) {
1795			range = bus_cur->rangeIO;
1796			for (i = 0; i < bus_cur->noIORanges; i++) {
1797				debug_pci ("rangeno is %d\n", range->rangeno);
1798				debug_pci ("[%x - %x]\n", range->start, range->end);
1799				range = range->next;
1800			}
1801		}
1802
1803		debug_pci ("The Mem Ranges are as follows:\n");
1804		if (bus_cur->rangeMem) {
1805			range = bus_cur->rangeMem;
1806			for (i = 0; i < bus_cur->noMemRanges; i++) {
1807				debug_pci ("rangeno is %d\n", range->rangeno);
1808				debug_pci ("[%x - %x]\n", range->start, range->end);
1809				range = range->next;
1810			}
1811		}
1812
1813		debug_pci ("The PFMem Ranges are as follows:\n");
1814
1815		if (bus_cur->rangePFMem) {
1816			range = bus_cur->rangePFMem;
1817			for (i = 0; i < bus_cur->noPFMemRanges; i++) {
1818				debug_pci ("rangeno is %d\n", range->rangeno);
1819				debug_pci ("[%x - %x]\n", range->start, range->end);
1820				range = range->next;
1821			}
1822		}
1823
1824		debug_pci ("The resources on this bus are as follows\n");
1825
1826		debug_pci ("IO...\n");
1827		if (bus_cur->firstIO) {
1828			res = bus_cur->firstIO;
1829			while (res) {
1830				debug_pci ("The range # is %d\n", res->rangeno);
1831				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
1832				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
1833				if (res->next)
1834					res = res->next;
1835				else if (res->nextRange)
1836					res = res->nextRange;
1837				else
1838					break;
1839			}
1840		}
1841		debug_pci ("Mem...\n");
1842		if (bus_cur->firstMem) {
1843			res = bus_cur->firstMem;
1844			while (res) {
1845				debug_pci ("The range # is %d\n", res->rangeno);
1846				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
1847				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
1848				if (res->next)
1849					res = res->next;
1850				else if (res->nextRange)
1851					res = res->nextRange;
1852				else
1853					break;
1854			}
1855		}
1856		debug_pci ("PFMem...\n");
1857		if (bus_cur->firstPFMem) {
1858			res = bus_cur->firstPFMem;
1859			while (res) {
1860				debug_pci ("The range # is %d\n", res->rangeno);
1861				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
1862				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
1863				if (res->next)
1864					res = res->next;
1865				else if (res->nextRange)
1866					res = res->nextRange;
1867				else
1868					break;
1869			}
1870		}
1871
1872		debug_pci ("PFMemFromMem...\n");
1873		if (bus_cur->firstPFMemFromMem) {
1874			res = bus_cur->firstPFMemFromMem;
1875			while (res) {
1876				debug_pci ("The range # is %d\n", res->rangeno);
1877				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
1878				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
1879				res = res->next;
1880			}
1881		}
1882	}
1883	debug_pci ("***********************END***********************\n");
1884}
1885
1886static int range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type)
1887{
1888	struct range_node * range_cur = NULL;
1889	switch (type) {
1890		case IO:
1891			range_cur = bus_cur->rangeIO;
1892			break;
1893		case MEM:
1894			range_cur = bus_cur->rangeMem;
1895			break;
1896		case PFMEM:
1897			range_cur = bus_cur->rangePFMem;
1898			break;
1899		default:
1900			err ("wrong type passed to find out if range already exists\n");
1901			return -ENODEV;
1902	}
1903
1904	while (range_cur) {
1905		if ((range_cur->start == range->start) && (range_cur->end == range->end))
1906			return 1;
1907		range_cur = range_cur->next;
1908	}
1909
1910	return 0;
1911}
1912
1913/* This routine will read the windows for any PPB we have and update the
1914 * range info for the secondary bus, and will also input this info into
1915 * primary bus, since BIOS doesn't. This is for PPB that are in the system
1916 * on bootup.  For bridged cards that were added during previous load of the
1917 * driver, only the ranges and the bus structure are added, the devices are
1918 * added from NVRAM
1919 * Input: primary busno
1920 * Returns: none
1921 * Note: this function doesn't take into account IO restrictions etc,
1922 *	 so will only work for bridges with no video/ISA devices behind them It
1923 *	 also will not work for onboard PPB's that can have more than 1 *bus
1924 *	 behind them All these are TO DO.
1925 *	 Also need to add more error checkings... (from fnc returns etc)
1926 */
1927static int __init update_bridge_ranges (struct bus_node **bus)
1928{
1929	u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address;
1930	u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address;
1931	u32 start_address, end_address, upper_start, upper_end;
1932	struct bus_node *bus_sec;
1933	struct bus_node *bus_cur;
1934	struct resource_node *io;
1935	struct resource_node *mem;
1936	struct resource_node *pfmem;
1937	struct range_node *range;
1938	unsigned int devfn;
1939
1940	bus_cur = *bus;
1941	if (!bus_cur)
1942		return -ENODEV;
1943	ibmphp_pci_bus->number = bus_cur->busno;
1944
1945	debug ("inside %s\n", __func__);
1946	debug ("bus_cur->busno = %x\n", bus_cur->busno);
1947
1948	for (device = 0; device < 32; device++) {
1949		for (function = 0x00; function < 0x08; function++) {
1950			devfn = PCI_DEVFN(device, function);
1951			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
1952
1953			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
1954				/* found correct device!!! */
1955				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
1956
1957				switch (hdr_type) {
1958					case PCI_HEADER_TYPE_NORMAL:
1959						function = 0x8;
1960						break;
1961					case PCI_HEADER_TYPE_MULTIDEVICE:
1962						break;
1963					case PCI_HEADER_TYPE_BRIDGE:
1964						function = 0x8;
1965					case PCI_HEADER_TYPE_MULTIBRIDGE:
1966						/* We assume here that only 1 bus behind the bridge
1967						   TO DO: add functionality for several:
1968						   temp = secondary;
1969						   while (temp < subordinate) {
1970						   ...
1971						   temp++;
1972						   }
1973						 */
1974						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno);
1975						bus_sec = find_bus_wprev (sec_busno, NULL, 0);
1976						/* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */
1977						if (!bus_sec) {
1978							bus_sec = alloc_error_bus (NULL, sec_busno, 1);
1979							/* the rest will be populated during NVRAM call */
1980							return 0;
1981						}
1982						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address);
1983						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address);
1984						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start);
1985						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end);
1986						start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8;
1987						start_address |= (upper_io_start << 16);
1988						end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8;
1989						end_address |= (upper_io_end << 16);
1990
1991						if ((start_address) && (start_address <= end_address)) {
1992							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
1993							if (!range) {
1994								err ("out of system memory\n");
1995								return -ENOMEM;
1996							}
1997							range->start = start_address;
1998							range->end = end_address + 0xfff;
1999
2000							if (bus_sec->noIORanges > 0) {
2001								if (!range_exists_already (range, bus_sec, IO)) {
2002									add_bus_range (IO, range, bus_sec);
2003									++bus_sec->noIORanges;
2004								} else {
2005									kfree (range);
2006									range = NULL;
2007								}
2008							} else {
2009								/* 1st IO Range on the bus */
2010								range->rangeno = 1;
2011								bus_sec->rangeIO = range;
2012								++bus_sec->noIORanges;
2013							}
2014							fix_resources (bus_sec);
2015
2016							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
2017								io = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
2018								if (!io) {
2019									kfree (range);
2020									err ("out of system memory\n");
2021									return -ENOMEM;
2022								}
2023								io->type = IO;
2024								io->busno = bus_cur->busno;
2025								io->devfunc = ((device << 3) | (function & 0x7));
2026								io->start = start_address;
2027								io->end = end_address + 0xfff;
2028								io->len = io->end - io->start + 1;
2029								ibmphp_add_resource (io);
2030							}
2031						}
2032
2033						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);
2034						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address);
2035
2036						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
2037						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
2038
2039						if ((start_address) && (start_address <= end_address)) {
2040
2041							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
2042							if (!range) {
2043								err ("out of system memory\n");
2044								return -ENOMEM;
2045							}
2046							range->start = start_address;
2047							range->end = end_address + 0xfffff;
2048
2049							if (bus_sec->noMemRanges > 0) {
2050								if (!range_exists_already (range, bus_sec, MEM)) {
2051									add_bus_range (MEM, range, bus_sec);
2052									++bus_sec->noMemRanges;
2053								} else {
2054									kfree (range);
2055									range = NULL;
2056								}
2057							} else {
2058								/* 1st Mem Range on the bus */
2059								range->rangeno = 1;
2060								bus_sec->rangeMem = range;
2061								++bus_sec->noMemRanges;
2062							}
2063
2064							fix_resources (bus_sec);
2065
2066							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
2067								mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
2068								if (!mem) {
2069									kfree (range);
2070									err ("out of system memory\n");
2071									return -ENOMEM;
2072								}
2073								mem->type = MEM;
2074								mem->busno = bus_cur->busno;
2075								mem->devfunc = ((device << 3) | (function & 0x7));
2076								mem->start = start_address;
2077								mem->end = end_address + 0xfffff;
2078								mem->len = mem->end - mem->start + 1;
2079								ibmphp_add_resource (mem);
2080							}
2081						}
2082						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address);
2083						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address);
2084						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start);
2085						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end);
2086						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
2087						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
2088#if BITS_PER_LONG == 64
2089						start_address |= ((long) upper_start) << 32;
2090						end_address |= ((long) upper_end) << 32;
2091#endif
2092
2093						if ((start_address) && (start_address <= end_address)) {
2094
2095							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
2096							if (!range) {
2097								err ("out of system memory\n");
2098								return -ENOMEM;
2099							}
2100							range->start = start_address;
2101							range->end = end_address + 0xfffff;
2102
2103							if (bus_sec->noPFMemRanges > 0) {
2104								if (!range_exists_already (range, bus_sec, PFMEM)) {
2105									add_bus_range (PFMEM, range, bus_sec);
2106									++bus_sec->noPFMemRanges;
2107								} else {
2108									kfree (range);
2109									range = NULL;
2110								}
2111							} else {
2112								/* 1st PFMem Range on the bus */
2113								range->rangeno = 1;
2114								bus_sec->rangePFMem = range;
2115								++bus_sec->noPFMemRanges;
2116							}
2117
2118							fix_resources (bus_sec);
2119							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
2120								pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
2121								if (!pfmem) {
2122									kfree (range);
2123									err ("out of system memory\n");
2124									return -ENOMEM;
2125								}
2126								pfmem->type = PFMEM;
2127								pfmem->busno = bus_cur->busno;
2128								pfmem->devfunc = ((device << 3) | (function & 0x7));
2129								pfmem->start = start_address;
2130								pfmem->end = end_address + 0xfffff;
2131								pfmem->len = pfmem->end - pfmem->start + 1;
2132								pfmem->fromMem = 0;
2133
2134								ibmphp_add_resource (pfmem);
2135							}
2136						}
2137						break;
2138				}	/* end of switch */
2139			}	/* end if vendor */
2140		}	/* end for function */
2141	}	/* end for device */
2142
2143	bus = &bus_cur;
2144	return 0;
2145}
2146