Пример #1
0
asmlinkage int sys_olduname(struct oldold_utsname * name)
{
	int error;
	
	PPCDBG(PPCDBG_SYS64X, "sys_olduname - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);

	if (!name)
		return -EFAULT;
	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
		return -EFAULT;
  
	down_read(&uts_sem);
	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
	error -= __put_user(0,name->release+__OLD_UTS_LEN);
	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
	error -= __put_user(0,name->version+__OLD_UTS_LEN);
	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
	error = __put_user(0,name->machine+__OLD_UTS_LEN);
	up_read(&uts_sem);

	error = error ? -EFAULT : 0;
	
	PPCDBG(PPCDBG_SYS64X, "sys_olduname - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
	return error;
}
Пример #2
0
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
				  unsigned long prot, unsigned long flags,
				  unsigned long fd, off_t offset)
{
	struct file * file = NULL;
	unsigned long ret = -EBADF;

	PPCDBG(PPCDBG_SYS64X, "sys_mmap - entered - addr=%lx, len=%lx - pid=%ld, comm=%s \n", addr, len, current->pid, current->comm);
	
	if (!(flags & MAP_ANONYMOUS)) {
		if (!(file = fget(fd)))
			goto out;
	}
	
	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
	down_write(&current->mm->mmap_sem);
	ret = do_mmap(file, addr, len, prot, flags, offset);
	up_write(&current->mm->mmap_sem);
	if (file)
		fput(file);

out:
	
	PPCDBG(PPCDBG_SYS64X, "sys_mmap - exited - ret=%x \n", ret);
	
	return ret;
}
Пример #3
0
static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, 
				unsigned long uaddr, int direction )
{
	u64 set_tce_rc;
	union Tce tce;
	
	PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr);
	PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", 
	       tcenum, tbl, tbl->index);

	tce.wholeTce = 0;
	tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;

	tce.tceBits.readWrite = 1;
	if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1;

	set_tce_rc = plpar_tce_put((u64)tbl->index, 
				 (u64)tcenum << 12, 
				 tce.wholeTce );

	if(set_tce_rc) {
		printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", set_tce_rc);
		printk("\tindex   = 0x%lx\n", (u64)tbl->index);
		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
		printk("\ttce val = 0x%lx\n", tce.wholeTce );
	}
}
/******************************************************************
 * pci_read_irq_line
 *
 * Reads the Interrupt Pin to determine if interrupt is use by card.
 * If the interrupt is used, then gets the interrupt line from the 
 * openfirmware and sets it in the pci_dev and pci_config line.
 *
 ******************************************************************/
int 
pci_read_irq_line(struct pci_dev *Pci_Dev)
{
	u8 InterruptPin;
	struct device_node *Node;

    	pci_read_config_byte(Pci_Dev, PCI_INTERRUPT_PIN, &InterruptPin);
	if (InterruptPin == 0) {
		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",Pci_Dev->slot_name);
		return 0;	
	}

	Node = pci_device_to_OF_node(Pci_Dev);
	if ( Node == NULL) { 
		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",Pci_Dev->slot_name);
		return -1;	
	}
	if (Node->n_intrs == 0) 	{
		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",Pci_Dev->slot_name);
		return -1;	
	}
	Pci_Dev->irq = Node->intrs[0].line;

	if (s7a_workaround) {
		if (Pci_Dev->irq > 16)
			Pci_Dev->irq -= 3;
	}

	pci_write_config_byte(Pci_Dev, PCI_INTERRUPT_LINE, Pci_Dev->irq);
	
	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq);
	return 0;
}
Пример #5
0
asmlinkage int sys_pause(void)
{
	
	PPCDBG(PPCDBG_SYS64X, "sys_pause - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	
	PPCDBG(PPCDBG_SYS64X, "sys_pause - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
	return -ERESTARTNOHAND;
}
/*********************************************************************** 
 * ppc64_pcibios_init
 *  
 * Chance to initialize and structures or variable before PCI Bus walk.
 *  
 *<4>buswalk [swapper : iSeries_pcibios_init Entry.
 *<4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30
 *<4>buswalk [swapper : find_and_init_phbs Entry
 *<4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017
 *<4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00
 *<4>buswalk [swapper : iSeries_assign_IRQ   0x0017.00.12 = 0x0091
 *<4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91
 *<4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE
 *<4>buswalk [swapper : - build_device_node 0x17.28.12
 *<4>buswalk [swapper : iSeries_pcibios_init Exit.
 ***********************************************************************/
void iSeries_pcibios_init(void)
{
	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Entry.\n"); 

	iSeries_IoMmTable_Initialize();

	find_and_init_phbs();

	pci_assign_all_busses = 0;
	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); 
}
Пример #7
0
asmlinkage int sys_uname(struct old_utsname * name)
{
	int err = -EFAULT;
	
	PPCDBG(PPCDBG_SYS64X, "sys_uname - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);

	down_read(&uts_sem);
	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
		err = 0;
	up_read(&uts_sem);
	
	PPCDBG(PPCDBG_SYS64X, "sys_uname - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
	return err;
}
Пример #8
0
/*
 * Atomically swap in the new signal mask, and wait for a signal.
 */
long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
	       struct pt_regs *regs)
{
	sigset_t saveset;
  
        PPCDBG(PPCDBG_SYS64X, "sys_sigsuspend - running - pid=%ld current=%lx comm=%s \n",
                current->pid, current, current->comm);



	mask &= _BLOCKABLE;
	spin_lock_irq(&current->sigmask_lock);
	saveset = current->blocked;
	siginitset(&current->blocked, mask);
	recalc_sigpending(current);
	spin_unlock_irq(&current->sigmask_lock);

	regs->gpr[3] = -EINTR;
	while (1) {
		current->state = TASK_INTERRUPTIBLE;
		schedule();
		if (do_signal(&saveset, regs))
			/*
			 * If a signal handler needs to be called,
			 * do_signal() has set R3 to the signal number (the
			 * first argument of the signal handler), so don't
			 * overwrite that with EINTR !
			 * In the other cases, do_signal() doesn't touch 
			 * R3, so it's still set to -EINTR (see above).
			 */
			return regs->gpr[3];
	}
}
Пример #9
0
long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
		  int p7, struct pt_regs *regs)
{
	sigset_t saveset, newset;

  
        PPCDBG(PPCDBG_SYS64X, "sys_rt_sigsuspend - running - pid=%ld current=%lx comm=%s \n",
                current->pid, current, current->comm);
	
  /* XXX: Don't preclude handling different sized sigset_t's.  */
	if (sigsetsize != sizeof(sigset_t))
		return -EINVAL;

	if (copy_from_user(&newset, unewset, sizeof(newset)))
		return -EFAULT;
	sigdelsetmask(&newset, ~_BLOCKABLE);

	spin_lock_irq(&current->sigmask_lock);
	saveset = current->blocked;
	current->blocked = newset;
	recalc_sigpending(current);
	spin_unlock_irq(&current->sigmask_lock);

	regs->gpr[3] = -EINTR;
	while (1) {
		current->state = TASK_INTERRUPTIBLE;
		schedule();
		if (do_signal(&saveset, regs))
			return regs->gpr[3];
	}
}
Пример #10
0
/*
 * sys_pipe() is the normal C calling standard for creating
 * a pipe. It's not the way unix traditionally does this, though.
 */
asmlinkage int sys_pipe(int *fildes)
{
	int fd[2];
	int error;
	
	PPCDBG(PPCDBG_SYS64X, "sys_pipe - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);

	error = do_pipe(fd);
	if (!error) {
		if (copy_to_user(fildes, fd, 2*sizeof(int)))
			error = -EFAULT;
	}
	
	PPCDBG(PPCDBG_SYS64X, "sys_pipe - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
	return error;
}
void  iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel)
{
	struct HvCallPci_BridgeInfo* BridgeInfo;
	HvAgentId      AgentId;
	int            Function;
	int            HvRc;

	BridgeInfo = (struct HvCallPci_BridgeInfo*)kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
	if(BridgeInfo == NULL) return;

	/*********************************************************************
	 * Note: hvSubBus and irq is always be 0 at this level!
	 *********************************************************************/
	for (Function=0; Function < 8; ++Function) {
	  	AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
		HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0);
 		if (HvRc == 0) {
  			/*  Connect EADs: 0x18.00.12 = 0x00 */
			PPCDBG(PPCDBG_BUSWALK,"PCI:Connect EADs: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId);
			PCIFR(                    "Connect EADs: 0x%02X.%02X.%02X",  Bus, SubBus, AgentId);
	    		HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, 
			                                REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo));
	 		if (HvRc == 0) {
				PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
				       BridgeInfo->busUnitInfo.deviceType,
				       BridgeInfo->subBusNumber,
				       BridgeInfo->maxAgents,
				       BridgeInfo->maxSubBusNumber,
				       BridgeInfo->logicalSlotNumber);
				PCIFR(                     "BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X",
				       BridgeInfo->busUnitInfo.deviceType,
				       BridgeInfo->subBusNumber,
				       BridgeInfo->maxAgents,
				       BridgeInfo->maxSubBusNumber,
				       BridgeInfo->logicalSlotNumber);

				if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice)  {
					/* Scan_Bridge_Slot...: 0x18.00.12 */
					iSeries_Scan_Bridge_Slot(Bus,BridgeInfo);
				}
				else printk("PCI: Invalid Bridge Configuration(0x%02X)",BridgeInfo->busUnitInfo.deviceType);
			}
    		}
		else if(HvRc != 0x000B) pci_Log_Error("EADs Connect",Bus,SubBus,AgentId,HvRc);
	}
	kfree(BridgeInfo);
}
Пример #12
0
__openfirmware
long
rtas_call(int token, int nargs, int nret,
	  unsigned long *outputs, ...)
{
	va_list list;
	int i;
	unsigned long s;
	struct rtas_args *rtas_args = &(get_paca()->xRtas);

	PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
	PPCDBG(PPCDBG_RTAS, "\ttoken    = 0x%x\n", token);
	PPCDBG(PPCDBG_RTAS, "\tnargs    = %d\n", nargs);
	PPCDBG(PPCDBG_RTAS, "\tnret     = %d\n", nret);
	PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs);
	if (token == RTAS_UNKNOWN_SERVICE)
		return -1;

	rtas_args->token = token;
	rtas_args->nargs = nargs;
	rtas_args->nret  = nret;
	rtas_args->rets  = (rtas_arg_t *)&(rtas_args->args[nargs]);
	va_start(list, outputs);
	for (i = 0; i < nargs; ++i) {
		rtas_args->args[i] = (rtas_arg_t)LONG_LSW(va_arg(list, ulong));
		PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%lx\n", i, rtas_args->args[i]);
	}
	va_end(list);

	for (i = 0; i < nret; ++i)
	  rtas_args->rets[i] = 0;

#if 0   /* Gotta do something different here, use global lock for now... */
	spin_lock_irqsave(&rtas_args->lock, s);
#else
	spin_lock_irqsave(&rtas.lock, s);
#endif
	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
		(void *)__pa((unsigned long)rtas_args));
	enter_rtas((void *)__pa((unsigned long)rtas_args));
	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
#if 0   /* Gotta do something different here, use global lock for now... */
	spin_unlock_irqrestore(&rtas_args->lock, s);
#else
	spin_unlock_irqrestore(&rtas.lock, s);
#endif
	ifppcdebug(PPCDBG_RTAS) {
		for(i=0; i < nret ;i++)
			udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]);
	}

	if (nret > 1 && outputs != NULL)
		for (i = 0; i < nret-1; ++i)
			outputs[i] = rtas_args->rets[i+1];
	return (ulong)((nret > 0) ? rtas_args->rets[0] : 0);
}
Пример #13
0
asmlinkage long sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
  struct pt_regs *regs = (struct pt_regs *) &uss;
  
  PPCDBG(PPCDBG_SYS64X, "sys_sigaltstack - running - pid=%ld current=%lx comm=%s \n",
          current->pid, current, current->comm);

  return do_sigaltstack(uss, uoss, regs->gpr[1]);
}
Пример #14
0
void __init smp_commence(void)
{
	/*
	 *	Lets the callin's below out of their loop.
	 */
	PPCDBG(PPCDBG_SMP, "smp_commence: start\n"); 
	wmb();
	smp_commenced = 1;
}
Пример #15
0
int
rtas_token(const char *service)
{
	int *tokp;
	if (rtas.dev == NULL) {
		PPCDBG(PPCDBG_RTAS,"\tNo rtas device in device-tree...\n");
		return RTAS_UNKNOWN_SERVICE;
	}
	tokp = (int *) get_property(rtas.dev, service, NULL);
	return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
}
/***********************************************************************
 * iSeries_pcibios_fixup(void)  
 ***********************************************************************/
void __init iSeries_pcibios_fixup(void)
{
	struct pci_dev* PciDev;
	struct iSeries_Device_Node* DeviceNode;
	char   Buffer[256];
    	int    DeviceCount = 0;

	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup Entry.\n"); 
	/******************************************************/
	/* Fix up at the device node and pci_dev relationship */
	/******************************************************/
	mf_displaySrc(0xC9000100);

	pci_for_each_dev(PciDev) {
		DeviceNode = find_Device_Node(PciDev);
		if(DeviceNode != NULL) {
			++DeviceCount;
			PciDev->sysdata    = (void*)DeviceNode;
			DeviceNode->PciDev = PciDev;

			PPCDBG(PPCDBG_BUSWALK,"PciDev 0x%p <==> DevNode 0x%p\n",PciDev,DeviceNode );

			iSeries_allocateDeviceBars(PciDev);

			PPCDBGCALL(PPCDBG_BUSWALK,dumpPci_Dev(PciDev) );

			iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) );
			printk("%d. %s\n",DeviceCount,Buffer);

			create_pci_bus_tce_table((unsigned long)DeviceNode);
		} else {
			printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev);
		}
	}
	iSeries_IoMmTable_Status();

	iSeries_activate_IRQs();

	mf_displaySrc(0xC9000200);
}
/****************************************************************************
 *
 * unsigned int __init find_and_init_phbs(void)
 *
 * Description:
 *   This function checks for all possible system PCI host bridges that connect
 *   PCI buses.  The system hypervisor is queried as to the guest partition
 *   ownership status.  A pci_controller is build for any bus which is partially
 *   owned or fully owned by this guest partition.
 ****************************************************************************/
unsigned long __init find_and_init_phbs(void)
{
	struct      pci_controller* phb;
	HvBusNumber BusNumber;

	PPCDBG(PPCDBG_BUSWALK,"find_and_init_phbs Entry\n");

	/* Check all possible buses. */
	for (BusNumber = 0; BusNumber < 256; BusNumber++) {
		int RtnCode = HvCallXm_testBus(BusNumber);
		if (RtnCode == 0) {
			phb = pci_alloc_pci_controllerX("PHB HV", phb_type_hypervisor);
			if(phb == NULL) {
				printk("PCI: Allocate pci_controller failed.\n");
				PCIFR(      "Allocate pci_controller failed.");
				return -1;
			}
			phb->pci_mem_offset = phb->local_number = BusNumber;
			phb->first_busno  = BusNumber;
			phb->last_busno   = BusNumber;
			phb->ops          = &iSeries_pci_ops;

			PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",phb,BusNumber);
			PCIFR("Create iSeries PHB controller: %04X",BusNumber);

			/***************************************************/
			/* Find and connect the devices.                   */
			/***************************************************/
			iSeries_Scan_PHBs_Slots(phb);
		}
		/* Check for Unexpected Return code, a clue that something */
		/* has gone wrong.                                         */
		else if(RtnCode != 0x0301) {
			PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X",BusNumber,RtnCode);
		}

	}
	return 0;
}
Пример #18
0
/*  This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c */
void __init iSeries_init_IRQ(void)
{
	int i;
	for (i = 0; i < NR_IRQS; i++) {
		irq_desc[i].handler = &iSeries_IRQ_handler;
		irq_desc[i].status = 0;
		irq_desc[i].status |= IRQ_DISABLED;
		irq_desc[i].depth = 1;
		iSeries_init_irqMap(i);
	}
	/* Register PCI event handler and open an event path */
	PPCDBG(PPCDBG_BUSWALK,"Register PCI event handler and open an event path\n");
	XmPciLpEvent_init();
	return;
}
Пример #19
0
/** Return a copy of the detailed error text associated with the
 *  most recent failed call to rtas.  Because the error text
 *  might go stale if there are any other intervening rtas calls,
 *  this routine must be called atomically with whatever produced
 *  the error (i.e. with rtas.lock still held from the previous call).
 */
static int
__fetch_rtas_last_error(void)
{
	struct rtas_args err_args, save_args;
	u32 bufsz;

	bufsz = rtas_token ("rtas-error-log-max");
	if ((bufsz == RTAS_UNKNOWN_SERVICE) ||
	    (bufsz > RTAS_ERROR_LOG_MAX)) {
		printk (KERN_WARNING "RTAS: bad log buffer size %d\n", bufsz);
		bufsz = RTAS_ERROR_LOG_MAX;
	}

	err_args.token = rtas_token("rtas-last-error");
	err_args.nargs = 2;
	err_args.nret = 1;

	err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
	err_args.args[1] = bufsz;
	err_args.args[2] = 0;

	save_args = rtas.args;
	rtas.args = err_args;
	rtas.args.rets = (rtas_arg_t *)&(rtas.args.args[2]);

	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
	       __pa(&err_args));
	enter_rtas((void *)__pa((unsigned long)(&rtas.args)));
	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");

	err_args = rtas.args;
	rtas.args = save_args;

	err_args.rets = (rtas_arg_t *)&(err_args.args[2]);
	return err_args.rets[0];
}
Пример #20
0
/* This should be called sometime prior to buswalk (init_IRQ would be good) */
int XmPciLpEvent_init()
{
    int xRc;
    PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_init, Register Event type 0x%04X\n",HvLpEvent_Type_PciIo);

    xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, &XmPciLpEvent_handler);
    if (xRc == 0) {
        xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
        if (xRc != 0) {
            printk(KERN_ERR "XmPciLpEvent.c: open event path failed with rc 0x%x\n", xRc);
        }
    }
    else {
        printk(KERN_ERR "XmPciLpEvent.c: register handler failed with rc 0x%x\n", xRc);
    }
    return xRc;
}
Пример #21
0
long sys_sigaction(int sig, const struct old_sigaction *act,
	      struct old_sigaction *oact)
{
	struct k_sigaction new_ka, old_ka;
	int ret;

        PPCDBG(PPCDBG_SYS64X, "sys_sigaction - running - pid=%ld current=%lx comm=%s \n",
                current->pid, current, current->comm);

 

	if (act) {
		old_sigset_t mask;
		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
			return -EFAULT;
		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
		__get_user(mask, &act->sa_mask);
		siginitset(&new_ka.sa.sa_mask, mask);
	}

	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

	if (!ret && oact) {
		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
			return -EFAULT;
		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
	}


 

	return ret;
}
/***********************************************************************
 * build_device_node(u16 Bus, int SubBus, u8 DevFn)
 *
 ***********************************************************************/
struct iSeries_Device_Node* build_device_node(HvBusNumber Bus, HvSubBusNumber  SubBus, int AgentId, int Function)
{
	struct iSeries_Device_Node*  DeviceNode;

	PPCDBG(PPCDBG_BUSWALK,"-build_device_node 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function);

	DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
	if(DeviceNode == NULL) return NULL;

	memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) );
	list_add_tail(&DeviceNode->Device_List,&iSeries_Global_Device_List);
	/*DeviceNode->DsaAddr      = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32); */
	ISERIES_BUS(DeviceNode)       = Bus;
	ISERIES_SUBBUS(DeviceNode)    = SubBus;
	DeviceNode->DsaAddr.deviceId  = 0x10;
        DeviceNode->DsaAddr.barNumber = 0;
	DeviceNode->AgentId           = AgentId;
	DeviceNode->DevFn             = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId),Function );
	DeviceNode->IoRetry           = 0;
	iSeries_Get_Location_Code(DeviceNode);
	PCIFR("Device 0x%02X.%2X, Node:0x%p ",ISERIES_BUS(DeviceNode),ISERIES_DEVFUN(DeviceNode),DeviceNode);
	return DeviceNode;
}
Пример #23
0
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
	siginfo_t info;
	struct k_sigaction *ka;
	unsigned long frame, newsp;

	/*
	 * If the current thread is 32 bit - invoke the
	 * 32 bit signal handling code
	 */
	if (current->thread.flags & PPC_FLAG_32BIT)
		return do_signal32(oldset, regs);

        if (!oldset)
		oldset = &current->blocked;

	newsp = frame = 0;

	for (;;) {
		unsigned long signr;

                PPCDBG(PPCDBG_SIGNAL, "do_signal - (pre) dequeueing signal - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);
                PPCDBG(PPCDBG_SIGNAL, "do_signal - (aft) dequeueing signal - signal=%lx - pid=%ld current=%lx comm=%s \n", signr, current->pid, current, current->comm);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];

  
                PPCDBG(PPCDBG_SIGNAL, "do_signal - ka=%p, action handler=%lx \n", ka, ka->sa.sa_handler);

		if (ka->sa.sa_handler == SIG_IGN) {
                        PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_IGN logic \n");
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;
                        PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_DFL logic \n");

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			case SIGSTOP: {
				struct signal_struct *sig;
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				sig = current->p_pptr->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;
			}

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sig_exit(signr, exit_code, &info);
				/* NOTREACHED */
			}
		}

		if ( (ka->sa.sa_flags & SA_ONSTACK)
		     && (! on_sig_stack(regs->gpr[1])))
			newsp = (current->sas_ss_sp + current->sas_ss_size);
		else
			newsp = regs->gpr[1];
		newsp = frame = newsp - sizeof(struct sigregs);

		/* Whee!  Actually deliver the signal.  */
  
                PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
		handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
                PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
                break;
	}

	if (regs->trap == 0x0C00 /* System Call! */ &&
	    ((int)regs->result == -ERESTARTNOHAND ||
	     (int)regs->result == -ERESTARTSYS ||
	     (int)regs->result == -ERESTARTNOINTR)) {
                PPCDBG(PPCDBG_SIGNAL, "do_signal - going to back up & retry system call \n");
		regs->gpr[3] = regs->orig_gpr3;
		regs->nip -= 4;		/* Back up & retry system call */
		regs->result = 0;
	}

	if (newsp == frame)
          {
             PPCDBG(PPCDBG_SIGNAL, "do_signal - returning w/ no signal delivered \n");
             return 0;		/* no signals delivered */
           }
  
     

        if (ka->sa.sa_flags & SA_SIGINFO)
             setup_rt_frame(regs, (struct sigregs *) frame, newsp);
        else        
	    setup_frame(regs, (struct sigregs *) frame, newsp);
        PPCDBG(PPCDBG_SIGNAL, "do_signal - returning a signal was delivered \n");
	return 1;
}
Пример #24
0
/*
 * Set up a signal frame.
 */
static void
setup_frame(struct pt_regs *regs, struct sigregs *frame,
            unsigned long newsp)
{

	/* Handler is *really* a pointer to the function descriptor for
	 * the signal routine.  The first entry in the function
	 * descriptor is the entry address of signal and the second
	 * entry is the TOC value we need to use.
	 */
	struct funct_descr_entry {
		unsigned long entry;
		unsigned long toc;
	};
  
	struct funct_descr_entry * funct_desc_ptr;
	unsigned long temp_ptr;

	struct sigcontext_struct *sc = (struct sigcontext_struct *) newsp;
  
	if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
		goto badframe;
	if (regs->msr & MSR_FP)
		giveup_fpu(current);
	if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
	    || __copy_to_user(&frame->fp_regs, current->thread.fpr,
			      ELF_NFPREG * sizeof(double))
	    || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0])    /* li r0, __NR_sigreturn */
	    || __put_user(0x44000002UL, &frame->tramp[1]))   /* sc */
		goto badframe;
	flush_icache_range((unsigned long) &frame->tramp[0],
			   (unsigned long) &frame->tramp[2]);

	newsp -= __SIGNAL_FRAMESIZE;
	if ( get_user(temp_ptr, &sc->handler))
		goto badframe;
  
	funct_desc_ptr = ( struct funct_descr_entry *) temp_ptr;

	if (put_user(regs->gpr[1], (unsigned long *)newsp)
	    || get_user(regs->nip, & funct_desc_ptr ->entry)
	    || get_user(regs->gpr[2],& funct_desc_ptr->toc)
	    || get_user(regs->gpr[3], &sc->signal))
		goto badframe;
	regs->gpr[1] = newsp;
	regs->gpr[4] = (unsigned long) sc;
	regs->link = (unsigned long) frame->tramp;


	PPCDBG(PPCDBG_SIGNAL, "setup_frame - returning - regs->gpr[1]=%lx, regs->gpr[4]=%lx, regs->link=%lx \n",
	       regs->gpr[1], regs->gpr[4], regs->link);

	return;

 badframe:
	PPCDBG(PPCDBG_SIGNAL, "setup_frame - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp);  PPCDBG_ENTER_DEBUGGER();
#if DEBUG_SIG
	printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n",
	       regs, frame, newsp);
#endif
	do_exit(SIGSEGV);
}
Пример #25
0
int rtas_call(int token, int nargs, int nret, int *outputs, ...)
{
	va_list list;
	int i, logit = 0;
	unsigned long s;
	struct rtas_args *rtas_args;
	char * buff_copy = NULL;
	int ret;

	PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
	PPCDBG(PPCDBG_RTAS, "\ttoken    = 0x%x\n", token);
	PPCDBG(PPCDBG_RTAS, "\tnargs    = %d\n", nargs);
	PPCDBG(PPCDBG_RTAS, "\tnret     = %d\n", nret);
	PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs);
	if (token == RTAS_UNKNOWN_SERVICE)
		return -1;

	/* Gotta do something different here, use global lock for now... */
	spin_lock_irqsave(&rtas.lock, s);
	rtas_args = &rtas.args;

	rtas_args->token = token;
	rtas_args->nargs = nargs;
	rtas_args->nret  = nret;
	rtas_args->rets  = (rtas_arg_t *)&(rtas_args->args[nargs]);
	va_start(list, outputs);
	for (i = 0; i < nargs; ++i) {
		rtas_args->args[i] = va_arg(list, rtas_arg_t);
		PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%x\n", i, rtas_args->args[i]);
	}
	va_end(list);

	for (i = 0; i < nret; ++i)
		rtas_args->rets[i] = 0;

	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
		__pa(rtas_args));
	enter_rtas(__pa(rtas_args));
	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");

	/* A -1 return code indicates that the last command couldn't
	   be completed due to a hardware error. */
	if (rtas_args->rets[0] == -1)
		logit = (__fetch_rtas_last_error() == 0);

	ifppcdebug(PPCDBG_RTAS) {
		for(i=0; i < nret ;i++)
			udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]);
	}

	if (nret > 1 && outputs != NULL)
		for (i = 0; i < nret-1; ++i)
			outputs[i] = rtas_args->rets[i+1];
	ret = (nret > 0)? rtas_args->rets[0]: 0;

	/* Log the error in the unlikely case that there was one. */
	if (unlikely(logit)) {
		buff_copy = rtas_err_buf;
		if (mem_init_done) {
			buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
			if (buff_copy)
				memcpy(buff_copy, rtas_err_buf,
				       RTAS_ERROR_LOG_MAX);
		}
	}

	/* Gotta do something different here, use global lock for now... */
	spin_unlock_irqrestore(&rtas.lock, s);

	if (buff_copy) {
		log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
		if (mem_init_done)
			kfree(buff_copy);
	}
	return ret;
}
/********************************************************************************
* 
* This assumes that the node slot is always on the primary bus!
*
*********************************************************************************/
int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* BridgeInfo)
{
	struct iSeries_Device_Node* DeviceNode;
	HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
	u16       VendorId    = 0;
	int       HvRc        = 0;
	u8        Irq         = 0;
	int       IdSel       = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
	int       Function    = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
	HvAgentId AgentId     = ISERIES_PCI_AGENTID(IdSel, Function);
	HvAgentId EADsIdSel   = ISERIES_PCI_AGENTID(IdSel, Function);
	int       FirstSlotId = 0; 	

	/**********************************************************/
	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3)                */
	/**********************************************************/
  	Irq   = iSeries_allocate_IRQ(Bus, 0, AgentId);
	iSeries_assign_IRQ(Irq, Bus, 0, AgentId);
	PPCDBG(PPCDBG_BUSWALK,"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",Bus, 0, AgentId, Irq );

	/****************************************************************************
	 * Connect all functions of any device found.  
	 ****************************************************************************/
  	for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
    		for (Function = 0; Function < 8; ++Function) {
			AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
			HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq);
			if( HvRc == 0) {
				HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId);
				if( HvRc == 0) {
					/**********************************************************/
					/* FoundDevice: 0x18.28.10 = 0x12AE                       */
					/**********************************************************/
					PPCDBG(PPCDBG_BUSWALK,"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
					                                       Bus, SubBus, AgentId, VendorId);

					HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq);  
					if( HvRc != 0) {
						pci_Log_Error("PciCfgStore Irq Failed!",Bus,SubBus,AgentId,HvRc);
					}

					++DeviceCount;
					DeviceNode = build_device_node(Bus, SubBus, EADsIdSel, Function);
					DeviceNode->Vendor      = VendorId;
					DeviceNode->Irq         = Irq;
					DeviceNode->LogicalSlot = BridgeInfo->logicalSlotNumber;
					PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X",
					      DeviceCount,Bus, SubBus, AgentId,
					      DeviceNode->LogicalSlot,DeviceNode->Vendor);

					/***********************************************************
					 * On the first device/function, assign irq to slot
					 ***********************************************************/
					if(Function == 0) { 
						FirstSlotId = AgentId;
						// AHT iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId);
    					}
				}
				else pci_Log_Error("Read Vendor",Bus,SubBus,AgentId,HvRc);
			}
			else pci_Log_Error("Connect Bus Unit",Bus,SubBus, AgentId,HvRc);
		} /* for (Function = 0; Function < 8; ++Function) */
	} /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
	return HvRc;
}
/******************************************************************
 * Find all PHBs in the system and initialize a set of data 
 * structures to represent them.
 ******************************************************************/
unsigned long __init
find_and_init_phbs(void)
{
        struct device_node *Pci_Node;
        struct pci_controller *phb;
        unsigned int root_addr_size_words = 0, this_addr_size_words = 0;
	unsigned int this_addr_count = 0, range_stride;
        unsigned int *ui_ptr = NULL, *ranges;
        char *model;
	struct pci_range64 range;
	struct resource *res;
	unsigned int memno, rlen, i, index;
	unsigned int *opprop;
	int has_isa = 0;
        PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n"); 

	read_pci_config = rtas_token("read-pci-config");
	write_pci_config = rtas_token("write-pci-config");
	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
	ibm_write_pci_config = rtas_token("ibm,write-pci-config");

	if (naca->interrupt_controller == IC_OPEN_PIC) {
		opprop = (unsigned int *)get_property(find_path_device("/"),
				"platform-open-pic", NULL);
	}

	/* Get the root address word size. */
	ui_ptr = (unsigned int *) get_property(find_path_device("/"), 
					       "#size-cells", NULL);
	if (ui_ptr) {
		root_addr_size_words = *ui_ptr;
	} else {
		PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n"); 
		return(-1);
	}

	if (find_type_devices("isa")) {
		has_isa = 1;
		PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n"); 
	}

	index = 0;

	/******************************************************************
	* Find all PHB devices and create an object for them.
	******************************************************************/
	for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) {
		model = (char *) get_property(Pci_Node, "model", NULL);
		if (model != NULL)  {
			phb = alloc_phb(Pci_Node, model, root_addr_size_words);
			if (phb == NULL) return(-1);
		}
		else {
         		continue;
		}
		
		/* Get this node's address word size. */
		ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL);
		if (ui_ptr)
			this_addr_size_words = *ui_ptr;
		else
			this_addr_size_words = 1;
		/* Get this node's address word count. */
		ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL);
		if (ui_ptr)
			this_addr_count = *ui_ptr;
		else
			this_addr_count = 3;
		
		range_stride = this_addr_count + root_addr_size_words + this_addr_size_words;
	      
		memno = 0;
		phb->io_base_phys = 0;
         
		ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen);
		PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
                
		for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) {
		  	/* Put the PCI addr part of the current element into a 
			 * '64' struct. 
			 */
		  	range = *((struct pci_range64 *)(ranges + i));

			/* If this is a '32' element, map into a 64 struct. */
			if ((range_stride * sizeof(int)) == 
			   sizeof(struct pci_range32)) {
				range.parent_addr = 
					(unsigned long)(*(ranges + i + 3));
				range.size = 
					(((unsigned long)(*(ranges + i + 4)))<<32) | 
					(*(ranges + i + 5));
			} else {
				range.parent_addr = 
					(((unsigned long)(*(ranges + i + 3)))<<32) | 
					(*(ranges + i + 4));
				range.size = 
					(((unsigned long)(*(ranges + i + 5)))<<32) | 
					(*(ranges + i + 6));
			}
			
			PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr    = 0x%lx\n", 
			       range.parent_addr);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi  = 0x%lx\n", 
			       range.child_addr.a_hi);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n", 
			       range.child_addr.a_mid);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo  = 0x%lx\n", 
			       range.child_addr.a_lo);
			PPCDBG(PPCDBG_PHBINIT, "\trange.size           = 0x%lx\n", 
			       range.size);

			res = NULL;
		        switch ((range.child_addr.a_hi >> 24) & 0x3) {
			case 1:		/* I/O space */
				PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n");
				phb->io_base_phys = range.parent_addr;
				res = &phb->io_resource;
				res->name = Pci_Node->full_name;
				res->flags = IORESOURCE_IO;
				phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE);
				if (!pci_io_base) {
					pci_io_base = (unsigned long)phb->io_base_virt;
					if (has_isa)
						isa_io_base = pci_io_base;
				}
				res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
				res->start += (unsigned long)phb->io_base_virt - pci_io_base;
				res->end =   res->start + range.size - 1;
				res->parent = NULL;
				res->sibling = NULL;
				res->child = NULL;
				phb->pci_io_offset = range.parent_addr - 
					((((unsigned long)
					   range.child_addr.a_mid) << 32) | 
					 (range.child_addr.a_lo));
				PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset  = 0x%lx\n", 
				       phb->pci_io_offset);
			  	break;
			case 2:		/* mem space */
				PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n");
				phb->pci_mem_offset = range.parent_addr - 
					((((unsigned long)
					   range.child_addr.a_mid) << 32) | 
					 (range.child_addr.a_lo));
				PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n", 
				       phb->pci_mem_offset);
				if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) {
					res = &(phb->mem_resources[memno]);
					++memno;
					res->name = Pci_Node->full_name;
					res->flags = IORESOURCE_MEM;
					res->start = range.parent_addr;
					res->end =   range.parent_addr + range.size - 1;
					res->parent = NULL;
					res->sibling = NULL;
					res->child = NULL;
				}
			  	break;
			}
		}
		PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys   = 0x%lx\n", 
		       phb->io_base_phys); 
		PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", 
		       phb->pci_mem_offset); 

		if (naca->interrupt_controller == IC_OPEN_PIC) {
			int addr = root_addr_size_words * (index + 2) - 1;
			openpic_setup_ISU(index, opprop[addr]); 
		}
		index++;
	}
	pci_devs_phb_init();
	return 0;	 /*Success */
}
/***********************************************************************
 * fixup_resources(struct pci_dev *dev) 
 *	
 ***********************************************************************/
void fixup_resources(struct pci_dev *PciDev)
{
	PPCDBG(PPCDBG_BUSWALK,"fixup_resources PciDev %p\n",PciDev);
}   
/******************************************************************
 *
 * Allocate and partially initialize a structure to represent a PHB.
 *
 ******************************************************************/
struct pci_controller *
alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
{
	struct pci_controller *phb;
	unsigned int *ui_ptr = NULL, len;
	struct reg_property64 reg_struct;
	struct property *of_prop;
	int *bus_range;
	int *buid_vals;

	PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name); 
	PPCDBG(PPCDBG_PHBINIT, "\tdev             = 0x%lx\n", dev); 
	PPCDBG(PPCDBG_PHBINIT, "\tmodel           = 0x%lx\n", model); 
	PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words); 
  
	/* Found a PHB, now figure out where his registers are mapped. */
	ui_ptr = (unsigned int *) get_property(dev, "reg", &len);
	if (ui_ptr == NULL) {
		PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); 
		return(NULL);
	}

	if (addr_size_words == 1) {
		reg_struct.address = ((struct reg_property32 *)ui_ptr)->address;
		reg_struct.size    = ((struct reg_property32 *)ui_ptr)->size;
	} else {
		reg_struct = *((struct reg_property64 *)ui_ptr);
	}

	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address);
	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size    = 0x%lx\n", reg_struct.size); 

	/***************************************************************
	* Set chip specific data in the phb, including types & 
	* register pointers.
	***************************************************************/

	/****************************************************************
	* Python
	***************************************************************/
	if (strstr(model, "Python")) {
		PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n");
	        phb = pci_alloc_pci_controller("PHB PY",phb_type_python);
		if (phb == NULL) return NULL;
	
       		phb->cfg_addr = (volatile unsigned long *) 
			ioremap(reg_struct.address + 0xf8000, PAGE_SIZE);
		PPCDBG(PPCDBG_PHBINIT, "\tcfg_addr_r = 0x%lx\n", 
		       reg_struct.address + 0xf8000);
		PPCDBG(PPCDBG_PHBINIT, "\tcfg_addr_v = 0x%lx\n", 
		       phb->cfg_addr);
		phb->cfg_data = (char*)(phb->cfg_addr + 0x02);
       		phb->phb_regs = (volatile unsigned long *) 
			ioremap(reg_struct.address + 0xf7000, PAGE_SIZE);
		/* Python's register file is 1 MB in size. */
		phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 
					 0x100000); 

		/* 
		 * Firmware doesn't always clear this bit which is critical
		 * for good performance - Anton
		 */
		{
			volatile u32 *tmp, i;

#define PRG_CL_RESET_VALID 0x00010000

			tmp = (u32 *)((unsigned long)phb->chip_regs + 0xf6030);

			if (*tmp & PRG_CL_RESET_VALID) {
				printk("Python workaround: ");
				*tmp &= ~PRG_CL_RESET_VALID;
				/*
				 * We must read it back for changes to
				 * take effect
				 */
				i = *tmp;
				printk("reg0: %x\n", i);
			}
		}

	/***************************************************************
	* Speedwagon
	*   include Winnipeg as well for the time being.
	***************************************************************/
	} else if ((strstr(model, "Speedwagon")) || 
		   (strstr(model, "Winnipeg"))) {
		PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n");
	        phb = pci_alloc_pci_controller("PHB SW",phb_type_speedwagon);
		if (phb == NULL) return NULL;

		if (systemcfg->platform == PLATFORM_PSERIES) {
			phb->cfg_addr = (volatile unsigned long *) 
			  ioremap(reg_struct.address + 0x140, PAGE_SIZE);
			phb->cfg_data = (char*)(phb->cfg_addr - 0x02); /* minus is correct */
			phb->phb_regs = (volatile unsigned long *) 
			  ioremap(reg_struct.address, PAGE_SIZE);
			/* Speedwagon's register file is 1 MB in size. */
			phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),
						 0x100000); 
			PPCDBG(PPCDBG_PHBINIT, "\tmapping chip_regs from 0x%lx -> 0x%lx\n", 
			       reg_struct.address & 0xfffff, phb->chip_regs);
		} else {
			phb->cfg_addr = NULL;
			phb->cfg_data = NULL; 
			phb->phb_regs = NULL;
			phb->chip_regs = NULL;
		}

		phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8;
	} else {
/***********************************************************************
 * iSeries_pcibios_fixup_bus(int Bus)
 *
 ***********************************************************************/
void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus)
{
	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); 

}