⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iseries_vpdinfo.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
字号:
/************************************************************************//* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001. *//************************************************************************//* This code gets the card location of the hardware                     *//* 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, Feb 2, 2001                                               *//*   Ported to ppc64, August 20, 2001                                   *//* End Change Activity                                                  *//************************************************************************/#include <linux/init.h>#include <linux/pci.h>#include <asm/types.h>#include <asm/resource.h>#include <asm/iSeries/HvCallPci.h>#include <asm/iSeries/HvTypes.h>#include <asm/iSeries/mf.h>#include <asm/iSeries/LparData.h>#include <asm/iSeries/HvCallPci.h>//#include <asm/iSeries/iSeries_VpdInfo.h>#include <asm/iSeries/iSeries_pci.h>#include "pci.h"/************************************************//* Size of Bus VPD data                         *//************************************************/#define BUS_VPDSIZE      1024/************************************************//* Bus Vpd Tags                                 *//************************************************/#define  VpdEndOfDataTag   0x78#define  VpdEndOfAreaTag   0x79#define  VpdIdStringTag    0x82#define  VpdVendorAreaTag  0x84/************************************************//* Mfg Area Tags                                *//************************************************/#define  VpdFruFlag       0x4647     // "FG"#define  VpdFruFrameId    0x4649     // "FI"#define  VpdSlotMapFormat 0x4D46     // "MF"#define  VpdAsmPartNumber 0x504E     // "PN"#define  VpdFruSerial     0x534E     // "SN"#define  VpdSlotMap       0x534D     // "SM"/************************************************//* Structures of the areas                      *//************************************************/struct MfgVpdAreaStruct {	u16 Tag;	u8  TagLength;	u8  AreaData1;	u8  AreaData2;};typedef struct MfgVpdAreaStruct MfgArea;#define MFG_ENTRY_SIZE   3struct SlotMapStruct {	u8   AgentId;	u8   SecondaryAgentId;	u8   PhbId;	char CardLocation[3];	char Parms[8];	char Reserved[2];}; typedef struct SlotMapStruct SlotMap;#define SLOT_ENTRY_SIZE   16/**************************************************************** *                                                              * * Bus, Card, Board, FrameId, CardLocation.                     * ****************************************************************/LocationData* iSeries_GetLocationData(struct pci_dev* PciDev){	struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;	LocationData* LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL);	if (LocationPtr == NULL) {		printk("PCI: LocationData area allocation failed!\n");		return NULL;	}	memset(LocationPtr,0,LOCATION_DATA_SIZE);	LocationPtr->Bus              = ISERIES_BUS(DevNode);	LocationPtr->Board            = DevNode->Board;	LocationPtr->FrameId          = DevNode->FrameId;	LocationPtr->Card             = PCI_SLOT(DevNode->DevFn);	strcpy(&LocationPtr->CardLocation[0],&DevNode->CardLocation[0]);	return LocationPtr;}/************************************************************************//* Formats the device information.                                      *//* - Pass in pci_dev* pointer to the device.                            *//* - Pass in buffer to place the data.  Danger here is the buffer must  *//*   be as big as the client says it is.   Should be at least 128 bytes.*//* Return will the length of the string data put in the buffer.         *//* Format:                                                              *//* PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet *//* controller                                                           *//************************************************************************/int  iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize){	struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;	char*          BufPtr  = Buffer;	int            LineLen = 0;	if (DevNode == NULL) {		LineLen = sprintf(BufPtr+LineLen, "PCI: iSeries_Device_Information DevNode is NULL");		return LineLen;	}	if (BufferSize >= 128) {		LineLen =  sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ",				   ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),PciDev->vendor);		LineLen += sprintf(BufPtr+LineLen,"Frame%3d, Card %4s  ", DevNode->FrameId,DevNode->CardLocation);		if (pci_class_name(PciDev->class >> 8) == 0) {			LineLen += sprintf(BufPtr+LineLen,"0x%04X  ",(int)(PciDev->class >> 8));		}		else {			LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) );		}	}	return LineLen;}/************************************************************************//* Build a character string of the device location, Frame  1, Card  C10 *//************************************************************************/int   device_Location(struct pci_dev* PciDev,char* BufPtr){	struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;	return sprintf(BufPtr,"PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s",		       DevNode->DsaAddr.busNumber,		       DevNode->AgentId,		       DevNode->Vendor,		       DevNode->Location);}/*****************************************************************//* Parse the Slot Area                                           *//*****************************************************************/void  iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, struct iSeries_Device_Node* DevNode){	int      SlotMapLen = MapLen;	SlotMap* SlotMapPtr = MapPtr;	/*************************************************************/	/* Parse Slot label until we find the one requrested         */	/*************************************************************/	while (SlotMapLen > 0) {		if ((SlotMapPtr->AgentId == DevNode->AgentId) && 		    (SlotMapPtr->SecondaryAgentId == 0x10   ) ) {			/*******************************************************/			/* If Phb wasn't found, grab the entry first one found.*/ 			/*******************************************************/			if (DevNode->PhbId == 0xff) {				DevNode->PhbId = SlotMapPtr->PhbId; 			}			/**************************************************/			/* Found it, extract the data.                    */			/**************************************************/			if (SlotMapPtr->PhbId == DevNode->PhbId ) {	        		memcpy(&DevNode->CardLocation,&SlotMapPtr->CardLocation,3);				DevNode->CardLocation[3]  = 0;				break;			}		}		/*********************************************************/		/* Point to the next Slot                                */		/*********************************************************/		SlotMapPtr = (SlotMap*)((char*)SlotMapPtr+SLOT_ENTRY_SIZE);		SlotMapLen -= SLOT_ENTRY_SIZE;	}}/*****************************************************************//* Parse the Mfg Area                                            *//*****************************************************************/static void  iSeries_Parse_MfgArea(u8* AreaData,int AreaLen, struct iSeries_Device_Node* DevNode){	MfgArea* MfgAreaPtr = (MfgArea*)AreaData;	int      MfgAreaLen = AreaLen;	u16      SlotMapFmt = 0;	/*************************************************************/	/* Parse Mfg Data                                            */	/*************************************************************/	while (MfgAreaLen > 0) {		int MfgTagLen  = MfgAreaPtr->TagLength;		/*******************************************************/		/* Frame ID         (FI 4649020310 )                   */		/*******************************************************/		if (MfgAreaPtr->Tag == VpdFruFrameId) {     /* FI  */			DevNode->FrameId = MfgAreaPtr->AreaData1;		}		/*******************************************************/		/* Slot Map Format  (MF 4D46020004 )                   */		/*******************************************************/		else if (MfgAreaPtr->Tag == VpdSlotMapFormat){   /* MF  */			SlotMapFmt = (MfgAreaPtr->AreaData1*256)+(MfgAreaPtr->AreaData2);		}		/*******************************************************/		/* Slot Map         (SM 534D90                         */		/*******************************************************/		else if (MfgAreaPtr->Tag == VpdSlotMap){         /* SM  */			SlotMap*  SlotMapPtr;			if (SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE+1); 	    		else                     SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE);	    		iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, DevNode);		}		/*********************************************************/		/* Point to the next Mfg Area                            */		/* Use defined size, sizeof give wrong answer            */		/*********************************************************/		MfgAreaPtr = (MfgArea*)((char*)MfgAreaPtr + MfgTagLen + MFG_ENTRY_SIZE);		MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); 	}	}/*****************************************************************//* Look for "BUS".. Data is not Null terminated.                 *//* PHBID of 0xFF indicates PHB was not found in VPD Data.        */	/*****************************************************************/static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength){	u8*  PhbPtr  = AreaPtr;	int  DataLen = AreaLength;	char PhbId   = 0xFF;                   	while (DataLen > 0) {		if (*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') {			PhbPtr += 3;			while(*PhbPtr == ' ') ++PhbPtr;			PhbId = (*PhbPtr & 0x0F);			break;        	}		++PhbPtr;		--DataLen;	}	return PhbId;}/****************************************************************//* Parse out the VPD Areas                                      *//****************************************************************/static void  iSeries_Parse_Vpd(u8* VpdData, int VpdDataLen, struct iSeries_Device_Node* DevNode){	u8*  TagPtr  = VpdData;	int  DataLen = VpdDataLen-3;	/*************************************************************/	/* Parse the Areas                                           */	/*************************************************************/	while (*TagPtr != VpdEndOfAreaTag && DataLen > 0) {		int  AreaLen   = *(TagPtr+1) + (*(TagPtr+2)*256);			u8*  AreaData  = TagPtr+3;		if (*TagPtr == VpdIdStringTag) {			DevNode->PhbId = iSeries_Parse_PhbId(AreaData,AreaLen);		}		else if (*TagPtr == VpdVendorAreaTag) {	    		iSeries_Parse_MfgArea(AreaData,AreaLen,DevNode);		}		/*********************************************************		 * Point to next Area.		 *********************************************************/		TagPtr  = AreaData + AreaLen;		DataLen -= AreaLen;	}}    /**************************************************************** *  iSeries_Get_Location_Code(struct iSeries_Device_Node*)      * * ****************************************************************/void  iSeries_Get_Location_Code(struct iSeries_Device_Node* DevNode){	int  BusVpdLen = 0;	u8*  BusVpdPtr = (u8*)kmalloc(BUS_VPDSIZE, GFP_KERNEL);	if (BusVpdPtr == NULL) {		printk("PCI: Bus VPD Buffer allocation failure.\n");		return;	}	BusVpdLen  = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),REALADDR(BusVpdPtr),BUS_VPDSIZE);	if (BusVpdLen == 0) {		kfree(BusVpdPtr);		printk("PCI: Bus VPD Buffer zero length.\n");		return;	}	//printk("PCI: DevNode:0x%p BusVpdPtr:0x%p Length:%d\n",DevNode, BusVpdPtr, BusVpdLen);	/*************************************************************/	/* Make sure this is what I think it is                      */	/*************************************************************/	if (*BusVpdPtr != VpdIdStringTag) {               /*0x82     */		printk("PCI: Bus VPD Buffer missing starting tag.\n");		kfree(BusVpdPtr);		return;	}	/***************************************************************/	/***************************************************************/	iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);	sprintf(DevNode->Location,"Frame%3d, Card %-4s",DevNode->FrameId,DevNode->CardLocation);	kfree(BusVpdPtr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -