iSeries_VpdInfo.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /************************************************************************/
  2. /* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001. */
  3. /************************************************************************/
  4. /* This code gets the card location of the hardware                     */
  5. /* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
  6. /*                                                                      */
  7. /* This program is free software; you can redistribute it and/or modify */
  8. /* it under the terms of the GNU General Public License as published by */
  9. /* the Free Software Foundation; either version 2 of the License, or    */
  10. /* (at your option) any later version.                                  */
  11. /*                                                                      */
  12. /* This program is distributed in the hope that it will be useful,      */ 
  13. /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
  14. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
  15. /* GNU General Public License for more details.                         */
  16. /*                                                                      */
  17. /* You should have received a copy of the GNU General Public License    */ 
  18. /* along with this program; if not, write to the:                       */
  19. /* Free Software Foundation, Inc.,                                      */ 
  20. /* 59 Temple Place, Suite 330,                                          */ 
  21. /* Boston, MA  02111-1307  USA                                          */
  22. /************************************************************************/
  23. /* Change Activity:                                                     */
  24. /*   Created, Feb 2, 2001                                               */
  25. /*   Ported to ppc64, August 20, 2001                                   */
  26. /* End Change Activity                                                  */
  27. /************************************************************************/
  28. #include <linux/init.h>
  29. #include <linux/pci.h>
  30. #include <asm/types.h>
  31. #include <asm/resource.h>
  32. #include <asm/iSeries/HvCallPci.h>
  33. #include <asm/iSeries/HvTypes.h>
  34. #include <asm/iSeries/mf.h>
  35. #include <asm/iSeries/LparData.h>
  36. #include <asm/iSeries/HvCallPci.h>
  37. //#include <asm/iSeries/iSeries_VpdInfo.h>
  38. #include <asm/iSeries/iSeries_pci.h>
  39. #include "pci.h"
  40. /************************************************/
  41. /* Size of Bus VPD data                         */
  42. /************************************************/
  43. #define BUS_VPDSIZE      1024
  44. /************************************************/
  45. /* Bus Vpd Tags                                 */
  46. /************************************************/
  47. #define  VpdEndOfDataTag   0x78
  48. #define  VpdEndOfAreaTag   0x79
  49. #define  VpdIdStringTag    0x82
  50. #define  VpdVendorAreaTag  0x84
  51. /************************************************/
  52. /* Mfg Area Tags                                */
  53. /************************************************/
  54. #define  VpdFruFlag       0x4647     // "FG"
  55. #define  VpdFruFrameId    0x4649     // "FI"
  56. #define  VpdSlotMapFormat 0x4D46     // "MF"
  57. #define  VpdAsmPartNumber 0x504E     // "PN"
  58. #define  VpdFruSerial     0x534E     // "SN"
  59. #define  VpdSlotMap       0x534D     // "SM"
  60. /************************************************/
  61. /* Structures of the areas                      */
  62. /************************************************/
  63. struct MfgVpdAreaStruct {
  64. u16 Tag;
  65. u8  TagLength;
  66. u8  AreaData1;
  67. u8  AreaData2;
  68. };
  69. typedef struct MfgVpdAreaStruct MfgArea;
  70. #define MFG_ENTRY_SIZE   3
  71. struct SlotMapStruct {
  72. u8   AgentId;
  73. u8   SecondaryAgentId;
  74. u8   PhbId;
  75. char CardLocation[3];
  76. char Parms[8];
  77. char Reserved[2];
  78. }; 
  79. typedef struct SlotMapStruct SlotMap;
  80. #define SLOT_ENTRY_SIZE   16
  81. /****************************************************************
  82.  *                                                              *
  83.  * Bus, Card, Board, FrameId, CardLocation.                     *
  84.  ****************************************************************/
  85. LocationData* iSeries_GetLocationData(struct pci_dev* PciDev)
  86. {
  87. struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;
  88. LocationData* LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL);
  89. if (LocationPtr == NULL) {
  90. printk("PCI: LocationData area allocation failed!n");
  91. return NULL;
  92. }
  93. memset(LocationPtr,0,LOCATION_DATA_SIZE);
  94. LocationPtr->Bus              = ISERIES_BUS(DevNode);
  95. LocationPtr->Board            = DevNode->Board;
  96. LocationPtr->FrameId          = DevNode->FrameId;
  97. LocationPtr->Card             = PCI_SLOT(DevNode->DevFn);
  98. strcpy(&LocationPtr->CardLocation[0],&DevNode->CardLocation[0]);
  99. return LocationPtr;
  100. }
  101. /************************************************************************/
  102. /* Formats the device information.                                      */
  103. /* - Pass in pci_dev* pointer to the device.                            */
  104. /* - Pass in buffer to place the data.  Danger here is the buffer must  */
  105. /*   be as big as the client says it is.   Should be at least 128 bytes.*/
  106. /* Return will the length of the string data put in the buffer.         */
  107. /* Format:                                                              */
  108. /* PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet */
  109. /* controller                                                           */
  110. /************************************************************************/
  111. int  iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize)
  112. {
  113. struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;
  114. char*          BufPtr  = Buffer;
  115. int            LineLen = 0;
  116. if (DevNode == NULL) {
  117. LineLen = sprintf(BufPtr+LineLen, "PCI: iSeries_Device_Information DevNode is NULL");
  118. return LineLen;
  119. }
  120. if (BufferSize >= 128) {
  121. LineLen =  sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ",
  122.    ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),PciDev->vendor);
  123. LineLen += sprintf(BufPtr+LineLen,"Frame%3d, Card %4s  ", DevNode->FrameId,DevNode->CardLocation);
  124. if (pci_class_name(PciDev->class >> 8) == 0) {
  125. LineLen += sprintf(BufPtr+LineLen,"0x%04X  ",(int)(PciDev->class >> 8));
  126. }
  127. else {
  128. LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) );
  129. }
  130. }
  131. return LineLen;
  132. }
  133. /************************************************************************/
  134. /* Build a character string of the device location, Frame  1, Card  C10 */
  135. /************************************************************************/
  136. int   device_Location(struct pci_dev* PciDev,char* BufPtr)
  137. {
  138. struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata;
  139. return sprintf(BufPtr,"PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s",
  140.        DevNode->DsaAddr.busNumber,
  141.        DevNode->AgentId,
  142.        DevNode->Vendor,
  143.        DevNode->Location);
  144. }
  145. /*****************************************************************/
  146. /* Parse the Slot Area                                           */
  147. /*****************************************************************/
  148. void  iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, struct iSeries_Device_Node* DevNode)
  149. {
  150. int      SlotMapLen = MapLen;
  151. SlotMap* SlotMapPtr = MapPtr;
  152. /*************************************************************/
  153. /* Parse Slot label until we find the one requrested         */
  154. /*************************************************************/
  155. while (SlotMapLen > 0) {
  156. if (SlotMapPtr->AgentId == DevNode->AgentId ) {
  157. /*******************************************************/
  158. /* If Phb wasn't found, grab the entry first one found.*/ 
  159. /*******************************************************/
  160. if (DevNode->PhbId == 0xff) {
  161. DevNode->PhbId = SlotMapPtr->PhbId; 
  162. }
  163. /**************************************************/
  164. /* Found it, extract the data.                    */
  165. /**************************************************/
  166. if (SlotMapPtr->PhbId == DevNode->PhbId ) {
  167.          memcpy(&DevNode->CardLocation,&SlotMapPtr->CardLocation,3);
  168. DevNode->CardLocation[3]  = 0;
  169. break;
  170. }
  171. }
  172. /*********************************************************/
  173. /* Point to the next Slot                                */
  174. /*********************************************************/
  175. SlotMapPtr = (SlotMap*)((char*)SlotMapPtr+SLOT_ENTRY_SIZE);
  176. SlotMapLen -= SLOT_ENTRY_SIZE;
  177. }
  178. }
  179. /*****************************************************************/
  180. /* Parse the Mfg Area                                            */
  181. /*****************************************************************/
  182. static void  iSeries_Parse_MfgArea(u8* AreaData,int AreaLen, struct iSeries_Device_Node* DevNode)
  183. {
  184. MfgArea* MfgAreaPtr = (MfgArea*)AreaData;
  185. int      MfgAreaLen = AreaLen;
  186. u16      SlotMapFmt = 0;
  187. /*************************************************************/
  188. /* Parse Mfg Data                                            */
  189. /*************************************************************/
  190. while (MfgAreaLen > 0) {
  191. int MfgTagLen  = MfgAreaPtr->TagLength;
  192. /*******************************************************/
  193. /* Frame ID         (FI 4649020310 )                   */
  194. /*******************************************************/
  195. if (MfgAreaPtr->Tag == VpdFruFrameId) {     /* FI  */
  196. DevNode->FrameId = MfgAreaPtr->AreaData1;
  197. }
  198. /*******************************************************/
  199. /* Slot Map Format  (MF 4D46020004 )                   */
  200. /*******************************************************/
  201. else if (MfgAreaPtr->Tag == VpdSlotMapFormat){   /* MF  */
  202. SlotMapFmt = (MfgAreaPtr->AreaData1*256)+(MfgAreaPtr->AreaData2);
  203. }
  204. /*******************************************************/
  205. /* Slot Map         (SM 534D90                         */
  206. /*******************************************************/
  207. else if (MfgAreaPtr->Tag == VpdSlotMap){         /* SM  */
  208. SlotMap*  SlotMapPtr;
  209. if (SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE+1);
  210.        else                     SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE);
  211.      iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, DevNode);
  212. }
  213. /*********************************************************/
  214. /* Point to the next Mfg Area                            */
  215. /* Use defined size, sizeof give wrong answer            */
  216. /*********************************************************/
  217. MfgAreaPtr = (MfgArea*)((char*)MfgAreaPtr + MfgTagLen + MFG_ENTRY_SIZE);
  218. MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); 
  219. }
  220. }
  221. /*****************************************************************/
  222. /* Look for "BUS".. Data is not Null terminated.                 */
  223. /* PHBID of 0xFF indicates PHB was not found in VPD Data.        */
  224. /*****************************************************************/
  225. static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength)
  226. {
  227. u8*  PhbPtr  = AreaPtr;
  228. int  DataLen = AreaLength;
  229. char PhbId   = 0xFF;                   
  230. while (DataLen > 0) {
  231. if (*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') {
  232. PhbPtr += 3;
  233. while(*PhbPtr == ' ') ++PhbPtr;
  234. PhbId = (*PhbPtr & 0x0F);
  235. break;
  236.          }
  237. ++PhbPtr;
  238. --DataLen;
  239. }
  240. return PhbId;
  241. }
  242. /****************************************************************/
  243. /* Parse out the VPD Areas                                      */
  244. /****************************************************************/
  245. static void  iSeries_Parse_Vpd(u8* VpdData, int VpdDataLen, struct iSeries_Device_Node* DevNode)
  246. {
  247. u8*  TagPtr  = VpdData;
  248. int  DataLen = VpdDataLen-3;
  249. /*************************************************************/
  250. /* Parse the Areas                                           */
  251. /*************************************************************/
  252. while (*TagPtr != VpdEndOfAreaTag && DataLen > 0) {
  253. int  AreaLen   = *(TagPtr+1) + (*(TagPtr+2)*256);
  254. u8*  AreaData  = TagPtr+3;
  255. if (*TagPtr == VpdIdStringTag) {
  256. DevNode->PhbId = iSeries_Parse_PhbId(AreaData,AreaLen);
  257. }
  258. else if (*TagPtr == VpdVendorAreaTag) {
  259.      iSeries_Parse_MfgArea(AreaData,AreaLen,DevNode);
  260. }
  261. /*********************************************************
  262.  * Point to next Area.
  263.  *********************************************************/
  264. TagPtr  = AreaData + AreaLen;
  265. DataLen -= AreaLen;
  266. }
  267. }    
  268. /****************************************************************
  269.  *  iSeries_Get_Location_Code(struct iSeries_Device_Node*)      *
  270.  *
  271.  ****************************************************************/
  272. void  iSeries_Get_Location_Code(struct iSeries_Device_Node* DevNode)
  273. {
  274. int  BusVpdLen = 0;
  275. u8*  BusVpdPtr = (u8*)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
  276. if (BusVpdPtr == NULL) {
  277. printk("PCI: Bus VPD Buffer allocation failure.n");
  278. return;
  279. }
  280. BusVpdLen  = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),REALADDR(BusVpdPtr),BUS_VPDSIZE);
  281. if (BusVpdLen == 0) {
  282. kfree(BusVpdPtr);
  283. printk("PCI: Bus VPD Buffer zero length.n");
  284. return;
  285. }
  286. //printk("PCI: BusVpdPtr: %p, %dn",BusVpdPtr, BusVpdLen);
  287. /*************************************************************/
  288. /* Make sure this is what I think it is                      */
  289. /*************************************************************/
  290. if (*BusVpdPtr != VpdIdStringTag) {               /*0x82     */
  291. printk("PCI: Bus VPD Buffer missing starting tag.n");
  292. kfree(BusVpdPtr);
  293. return;
  294. }
  295. /***************************************************************/
  296. /***************************************************************/
  297. iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);
  298. sprintf(DevNode->Location,"Frame%3d, Card %-4s",DevNode->FrameId,DevNode->CardLocation);
  299. kfree(BusVpdPtr);
  300. }