/*******************************************************************************
 *	PupeGeog.cpp	Pupe Bus Slot Location class
 *			T.Barnaby,	BEAM Ltd,	2007-09-16
 *******************************************************************************
 *
 *	Note that this code is hardwired for the
 *		Concurrent Technologies PP 41x/03x board.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
extern "C" {
#include <pci/pci.h>
}
#include <PupeGeog.h>

#define	DEBUG_GEOG	0

PupeGeog::PupeGeog(){
	int			s;

	for(s = 0; s < MaxNumBoards; s++){
		oboards[s] = -1;
	}
}

BError PupeGeog::scan(BArray<int> devs){
	BError			err;
	struct pci_access*	pacc;
	struct pci_dev*		dev;
	struct pci_dev*		devPrev = 0;
	int			s;
	int			b = 0;
	unsigned int		d;
	
	pacc = pci_alloc();
	pci_init(pacc);
	pci_scan_bus(pacc);

	for(s = 0; s < MaxNumBoards; s++){
		oboards[s] = -1;
	}
	
	for(dev = pacc->devices; dev; dev = dev->next){
#if DEBUG_GEOG
		printf("Dev: %d %d:%d:%d\n", dev->domain, dev->bus, dev->dev, dev->func);
		printf("	Vendor: %x:%x\n", dev->vendor_id, dev->device_id);
#endif
		if(dev->vendor_id == 0x4144){
			s = -1;
			for(d = 0; d < devs.size(); d++){
				if(dev->dev == devs[d]){
					s = d;
					break;
				}
			}

			if((s < 0) || (s >= MaxNumBoards)){
				return err.set(1, "Boards PCI Device value is out of range");
			}
			oboards[s] = b++;
		}
		devPrev = dev;
	}

	pci_cleanup(pacc);
	
	return err;
}

int PupeGeog::getBoardId(unsigned int slot){
	if(slot >= MaxNumBoards)
		return -1;
	else
		return oboards[slot];
}

#ifdef ZAP
int main(){
	BError		err;
	PupeGeog	pupeGeog;
	unsigned int	s;
	BArray<int>	devs(6);

	devs[0] = 9;
	devs[1] = 11;
	devs[2] = 12;
	devs[3] = 13;
	devs[4] = 14;
	devs[5] = 15;
	
	if(err = pupeGeog.scan(devs)){
		fprintf(stderr, "Scan error: %s\n", err.getString().retStr());
		return 1;
	}
	
	for(s = 0; s < 8; s++){
		printf("Slot: %d Board: %d\n", s, pupeGeog.getBoardId(s));
	}

	return 0;
}
#endif
