iseries_iommtable.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 207 行
C
207 行
/************************************************************************//* 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. *//* End Change Activity *//************************************************************************/#include <asm/types.h>#include <asm/resource.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <asm/iSeries/HvCallPci.h>#include <asm/iSeries/iSeries_FlightRecorder.h>#include "iSeries_IoMmTable.h"#include "iSeries_pci.h"void iSeries_allocateDeviceBars(struct pci_dev* PciDevPtr); /*******************************************************************//* Table defines *//* Entry size is 4 MB * 1024 Entries = 4GB. *//*******************************************************************/#define iSeries_IoMmTable_Entry_Size 0x00400000 #define iSeries_IoMmTable_Size 1024#define iSeries_Base_Io_Memory 0xFFFFFFFF/*******************************************************************//* Static and Global variables *//*******************************************************************/struct pci_dev* iSeries_IoMmTable[iSeries_IoMmTable_Size];u8 iSeries_IoBarTable[iSeries_IoMmTable_Size];static int iSeries_CurrentIndex;static char* iSeriesPciIoText = "iSeries PCI I/O";static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED;/*******************************************************************//* iSeries_IoMmTable_Initialize *//*******************************************************************//* - Initalizes the Address Translation Table and get it ready for *//* use. Must be called before any client calls any of the other *//* methods. *//*******************************************************************/void iSeries_IoMmTable_Initialize(void) { int Index; spin_lock(&iSeriesIoMmTableLock); for(Index=0;Index<iSeries_IoMmTable_Size ; ++Index) { iSeries_IoMmTable[Index] = NULL; iSeries_IoBarTable[Index] = 0xFF; } spin_unlock(&iSeriesIoMmTableLock); iSeries_CurrentIndex = iSeries_IoMmTable_Size-1; ISERIES_PCI_FR("IoMmTable Init.");}/*******************************************************************//* 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 resourses(0 - 5) including the the ROM *//* is resource(6). *//*******************************************************************/void iSeries_allocateDeviceBars(struct pci_dev* PciDevPtr) { struct resource* BarResource; int BarNumber = 0; /* Current Bar Number */ if(PciTraceFlag > 0) { printk("PCI: iSeries_allocateDeviceBars 0x%08X\n",(int)PciDevPtr); sprintf(PciFrBuffer,"IoBars %08X",(int)PciDevPtr); ISERIES_PCI_FR(PciFrBuffer); } for(BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) { BarResource = &PciDevPtr->resource[BarNumber]; iSeries_IoMmTable_AllocateEntry(PciDevPtr, BarNumber); }}/*******************************************************************//* iSeries_IoMmTable_AllocateEntry *//*******************************************************************//* Adds pci_dev entry in address translation table *//*******************************************************************//* - Allocates the number of entries required in table base on BAR *//* size. *//* - This version, allocates top down, starting at 4GB. *//* - The size is round up to be a multiple of entry size. *//* - CurrentIndex is decremented to keep track of the last entry. *//* - Builds the resource entry for allocated BARs. *//*******************************************************************/void iSeries_IoMmTable_AllocateEntry(struct pci_dev* PciDevPtr, u32 BarNumber) { struct resource* BarResource = &PciDevPtr->resource[BarNumber]; int BarSize = BarResource->end - BarResource->start; u32 BarStartAddr; u32 BarEndAddr; /***************************************************************/ /* No space to allocate, skip Allocation. */ /***************************************************************/ if(BarSize == 0) return; /* Quick stage exit */ /***************************************************************/ /* Allocate the table entries needed. */ /***************************************************************/ spin_lock(&iSeriesIoMmTableLock); while(BarSize > 0) { iSeries_IoMmTable[iSeries_CurrentIndex] = PciDevPtr; iSeries_IoBarTable[iSeries_CurrentIndex] = BarNumber; BarSize -= iSeries_IoMmTable_Entry_Size; --iSeries_CurrentIndex; /* Next Free entry */ } spin_unlock(&iSeriesIoMmTableLock); BarStartAddr = iSeries_IoMmTable_Entry_Size*(iSeries_CurrentIndex+1); BarEndAddr = BarStartAddr + (u32)(BarResource->end - BarResource->start); /***************************************************************/ /* Build Resource info */ /***************************************************************/ BarResource->name = iSeriesPciIoText; BarResource->start = (long)BarStartAddr; BarResource->end = (long)BarEndAddr; /***************************************************************/ /* Tracing */ /***************************************************************/ if(PciTraceFlag > 0) { printk("PCI: BarAloc %04X-%08X-%08X\n",iSeries_CurrentIndex+1,(int)BarStartAddr, (int)BarEndAddr); sprintf(PciFrBuffer,"IoMmAloc %04X-%08X-%08X", iSeries_CurrentIndex+1,(int)BarStartAddr, (int)BarEndAddr); ISERIES_PCI_FR(PciFrBuffer); }}/*******************************************************************//* Translates an I/O Memory address to pci_dev* *//*******************************************************************/struct pci_dev* iSeries_xlateIoMmAddress(u32* IoAddress) { int PciDevIndex; struct pci_dev* PciDevPtr; PciDevIndex = (u32)IoAddress/iSeries_IoMmTable_Entry_Size; PciDevPtr = iSeries_IoMmTable[PciDevIndex]; if(PciDevPtr == 0) { printk("PCI: Invalid I/O Address: 0x%08X\n",(int)IoAddress); sprintf(PciFrBuffer,"Invalid MMIO Address 0x%08X",(int)IoAddress); ISERIES_PCI_FR(PciFrBuffer); } return PciDevPtr;}/************************************************************************//* Returns the Bar number of Address *//************************************************************************/int iSeries_IoMmTable_Bar(u32 *IoAddress) { int BarIndex = (u32)IoAddress/iSeries_IoMmTable_Entry_Size; int BarNumber = iSeries_IoBarTable[BarIndex]; return BarNumber;}/************************************************************************//* Return the Bar Base Address or 0. *//************************************************************************/u32* iSeries_IoMmTable_BarBase(u32 *IoAddress) { u32 BaseAddr = -1; pciDev* PciDev = iSeries_xlateIoMmAddress(IoAddress); if(PciDev != 0) { int BarNumber = iSeries_IoMmTable_Bar(IoAddress); if(BarNumber != -1) { BaseAddr = (&PciDev->resource[BarNumber])->start; } } return (u32*)BaseAddr;}/************************************************************************//* Return the Bar offset within the Bar Space *//* Note: Assumes that address is valid. *//************************************************************************/u32 iSeries_IoMmTable_BarOffset(u32* IoAddress) { u32 BaseAddr = (u32)iSeries_IoMmTable_BarBase(IoAddress); return (u32)IoAddress-BaseAddr;}/************************************************************************//* Return 0 if Address is valid I/O Address *//************************************************************************/int iSeries_Is_IoMmAddress(unsigned long IoAddress) { if( iSeries_IoMmTable_Bar((u32*)IoAddress) == -1) return 1; else return 0;}/************************************************************************//* Helper Methods to get TableSize and TableSizeEntry. *//************************************************************************/u32 iSeries_IoMmTable_TableEntrySize(void) { return iSeries_IoMmTable_Entry_Size; }u32 iSeries_IoMmTable_TableSize(void) { return iSeries_IoMmTable_Size; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?