[BACK]Return to iSeries_IoMmTable.c CVS log [TXT][DIR] Up to [Development] / linux-2.6-xfs / arch / ppc64 / kernel

File: [Development] / linux-2.6-xfs / arch / ppc64 / kernel / Attic / iSeries_IoMmTable.c (download)

Revision 1.2, Thu Jan 29 19:23:16 2004 UTC (13 years, 8 months ago) by nathans
Branch: MAIN
Changes since 1.1: +94 -88 lines

Merge up to 2.6.2-rc2

#define PCIFR(...)
/************************************************************************/
/* This module supports the iSeries I/O Address translation mapping     */
/* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
/*                                                                      */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or    */
/* (at your option) any later version.                                  */
/*                                                                      */
/* This program is distributed in the hope that it will be useful,      */ 
/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
/* GNU General Public License for more details.                         */
/*                                                                      */
/* You should have received a copy of the GNU General Public License    */ 
/* along with this program; if not, write to the:                       */
/* Free Software Foundation, Inc.,                                      */ 
/* 59 Temple Place, Suite 330,                                          */ 
/* Boston, MA  02111-1307  USA                                          */
/************************************************************************/
/* Change Activity:                                                     */
/*   Created, December 14, 2000                                         */
/*   Added Bar table for IoMm performance.                              */
/*   Ported to ppc64                                                    */
/*   Added dynamic table allocation                                     */
/* End Change Activity                                                  */
/************************************************************************/
#include <asm/types.h>
#include <asm/resource.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <asm/ppcdebug.h>
#include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/iSeries_pci.h>

#include "iSeries_IoMmTable.h"
#include "pci.h"

/*
 * Table defines
 * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
 */
#define Max_Entries 1024
unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000; 
unsigned long iSeries_Base_Io_Memory       = 0xE000000000000000;
unsigned long iSeries_Max_Io_Memory        = 0xE000000000000000;
static   long iSeries_CurrentIndex         = 0;

/*
 * Lookup Tables.
 */
struct iSeries_Device_Node **iSeries_IoMmTable;
u8 *iSeries_IoBarTable;

/*
 * Static and Global variables
 */
static char *iSeriesPciIoText = "iSeries PCI I/O";
static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED;

/*
 * iSeries_IoMmTable_Initialize
 *
 * Allocates and initalizes the Address Translation Table and Bar
 * Tables to get them ready for use.  Must be called before any
 * I/O space is handed out to the device BARs.
 * A follow up method,iSeries_IoMmTable_Status can be called to
 * adjust the table after the device BARs have been assiged to
 * resize the table.
 */
void iSeries_IoMmTable_Initialize(void)
{
	spin_lock(&iSeriesIoMmTableLock);
	iSeries_IoMmTable  = kmalloc(sizeof(void *) * Max_Entries, GFP_KERNEL);
	iSeries_IoBarTable = kmalloc(sizeof(u8) * Max_Entries, GFP_KERNEL);
	spin_unlock(&iSeriesIoMmTableLock);
	PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable);
	if ((iSeries_IoMmTable == NULL) || (iSeries_IoBarTable == NULL))
		panic("PCI: I/O tables allocation failed.\n");
}

/*
 * iSeries_IoMmTable_AllocateEntry
 *
 * Adds pci_dev entry in address translation table
 *
 * - Allocates the number of entries required in table base on BAR
 *   size.
 * - Allocates starting at iSeries_Base_Io_Memory and increases.
 * - The size is round up to be a multiple of entry size.
 * - CurrentIndex is incremented to keep track of the last entry.
 * - Builds the resource entry for allocated BARs.
 */
static void iSeries_IoMmTable_AllocateEntry(struct pci_dev *PciDev,
		int BarNumber)
{
	struct resource *BarResource = &PciDev->resource[BarNumber];
	long BarSize = pci_resource_len(PciDev, BarNumber);

	/*
	 * No space to allocate, quick exit, skip Allocation.
	 */
	if (BarSize == 0)
		return;
	/*
	 * Set Resource values.
	 */
	spin_lock(&iSeriesIoMmTableLock);
	BarResource->name = iSeriesPciIoText;
	BarResource->start =
		iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex;
	BarResource->start += iSeries_Base_Io_Memory;
	BarResource->end = BarResource->start+BarSize-1;
	/*
	 * Allocate the number of table entries needed for BAR.
	 */
	while (BarSize > 0 ) {
		*(iSeries_IoMmTable + iSeries_CurrentIndex) =
			(struct iSeries_Device_Node *)PciDev->sysdata;
		*(iSeries_IoBarTable + iSeries_CurrentIndex) = BarNumber;
		BarSize -= iSeries_IoMmTable_Entry_Size;
		++iSeries_CurrentIndex;
	}
	iSeries_Max_Io_Memory = iSeries_Base_Io_Memory +
		(iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex);
	spin_unlock(&iSeriesIoMmTableLock);
}

/*
 * iSeries_allocateDeviceBars
 *
 * - Allocates ALL pci_dev BAR's and updates the resources with the
 *   BAR value.  BARS with zero length will have the resources
 *   The HvCallPci_getBarParms is used to get the size of the BAR
 *   space.  It calls iSeries_IoMmTable_AllocateEntry to allocate
 *   each entry.
 * - Loops through The Bar resources(0 - 5) including the ROM
 *   is resource(6).
 */
void iSeries_allocateDeviceBars(struct pci_dev *PciDev)
{
	struct resource *BarResource;
	int BarNumber;

	for (BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) {
		BarResource = &PciDev->resource[BarNumber];
		iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber);
    	}
}

/*
 * Translates the IoAddress to the device that is mapped to IoSpace.
 * This code is inlined, see the iSeries_pci.c file for the replacement.
 */
struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress)
{
	return NULL;	   
}

/*
 * Status hook for IoMmTable
 */
void iSeries_IoMmTable_Status(void)
{
	PCIFR("IoMmTable......: 0x%p", iSeries_IoMmTable);
	PCIFR("IoMmTable Range: 0x%p to 0x%p", iSeries_Base_Io_Memory,
			iSeries_Max_Io_Memory);
}