inventory.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Copyright (c) 1999 The Puffin Group */
  2. /* Written by David Kennedy and Alex deVries */
  3. #include <linux/types.h>
  4. #include <linux/kernel.h>
  5. #include <asm/hardware.h>
  6. #include <asm/io.h>
  7. #include <asm/pdc.h>
  8. /*
  9. ** Debug options
  10. **    DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
  11. */
  12. #undef DEBUG_PAT
  13. extern char *parisc_getHWtype(unsigned short hw_type);
  14. extern struct hp_device * register_module(void *hpa);
  15. extern void print_devices(char * buf);
  16. int pdc_hpa_processor(void *address);
  17. #ifndef __LP64__ 
  18. static u8 iodc_data[32] __attribute__ ((aligned (64)));
  19. static struct pdc_model model __attribute__ ((aligned (8)));
  20. #endif
  21. static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
  22. static struct pdc_hpa processor_hpa __attribute__ ((aligned (8)));
  23. static struct pdc_system_map module_result __attribute__ ((aligned (8)));
  24. static struct pdc_module_path module_path __attribute__ ((aligned (8)));
  25. #ifdef __LP64__
  26. #include <asm/pdcpat.h>
  27. int pdc_pat = 0;
  28. /*
  29. **  The module object is filled via PDC_PAT_CELL[Return Cell Module].
  30. **  If a module is found, register module will get the IODC bytes via
  31. **  pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
  32. **
  33. **  The IO view can be used by PDC_PAT_CELL[Return Cell Module]
  34. **  only for SBAs and LBAs.  This view will cause an invalid
  35. **  argument error for all other cell module types.
  36. **
  37. */
  38. static int
  39. pat_query_module( ulong pcell_loc, ulong mod_index)
  40. {
  41. extern int num_devices;
  42. extern struct hp_device devices[];
  43. pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
  44.         struct hp_device * dev = &devices[num_devices];
  45. uint64_t temp;             /* 64-bit scratch value */
  46. long status;               /* PDC return value status */
  47. /* return cell module (PA or Processor view) */
  48. status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index,
  49. PA_VIEW, & pa_pdc_cell);
  50. if (status != PDC_RET_OK) {
  51. /* no more cell modules or error */
  52. return status;
  53. }
  54. /*
  55. ** save parameters in the hp_device
  56. ** (The idea being the device driver will call pdc_pat_cell_module()
  57. ** and store the results in it's own data structure.)
  58. */
  59. dev->pcell_loc = pcell_loc;
  60. dev->mod_index = mod_index;
  61. /* save generic info returned from the call */
  62. /* REVISIT: who is the consumer of this? not sure yet... */
  63. dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
  64. dev->pmod_loc = pa_pdc_cell.mod_location;
  65. dev->mod_path = pa_pdc_cell.mod_path;
  66. temp = pa_pdc_cell.cba;
  67. register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */
  68. #ifdef DEBUG_PAT
  69. /* dump what we see so far... */
  70. switch (PAT_GET_ENTITY(dev->mod_info)) {
  71. ulong i;
  72. case PAT_ENTITY_PROC:
  73. printk ("PAT_ENTITY_PROC: id_eid 0x%lxn", pa_pdc_cell.mod[0]);
  74. break;
  75. case PAT_ENTITY_MEM:
  76. printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lxn",
  77. pa_pdc_cell.mod[0],
  78. pa_pdc_cell.mod[1],
  79. pa_pdc_cell.mod[2]);
  80. break;
  81. case PAT_ENTITY_CA:
  82. printk ("PAT_ENTITY_CA: %ldn",pcell_loc);
  83. break;
  84. case PAT_ENTITY_PBC:
  85. printk ("PAT_ENTITY_PBC: ");
  86. goto print_ranges;
  87. case PAT_ENTITY_SBA:
  88. printk ("PAT_ENTITY_SBA: ");
  89. goto print_ranges;
  90. case PAT_ENTITY_LBA:
  91. printk ("PAT_ENTITY_LBA: ");
  92. print_ranges:
  93. printk ("ranges %ldn", pa_pdc_cell.mod[1]);
  94. for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
  95. printk (" %ld: 0x%016lx 0x%016lx 0x%016lxn", i,
  96. pa_pdc_cell.mod[2+i*3], /* type */
  97. pa_pdc_cell.mod[3+i*3], /* start */
  98. pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */
  99. }
  100. printk("n");
  101. break;
  102. }
  103. #endif /* DEBUG_PAT */
  104. return PDC_RET_OK;
  105. }
  106. static int do_pat_inventory(void)
  107. {
  108. ulong mod_index=0;
  109. int status;
  110. ulong cell_num;
  111. ulong pcell_loc;
  112. pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK);
  113. if (!pdc_pat)
  114. {
  115. return 0;
  116. }
  117. cell_num = pdc_result[0]; /* Cell number call was made */
  118. /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */
  119. pcell_loc = pdc_result[1]; /* Physical location of the cell */
  120. #ifdef DEBUG_PAT
  121. printk("CELL_GET_NUMBER: 0x%lx 0x%lxn", cell_num, pcell_loc);
  122. #endif
  123.         status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num);
  124.         if (status == PDC_BAD_OPTION)
  125. {
  126. /* Prelude (and it's successors: Lclass, A400/500) only
  127. ** implement PDC_PAT_CELL sub-options 0 and 2.
  128. ** "Home cook'n is best anyhow!"
  129. */
  130. } else if (PDC_OK == status) {
  131. /* so far only Halfdome supports this */
  132. pcell_loc = pdc_result[0];
  133. } else {
  134. panic("WTF? CELL_GET_NUMBER give me invalid cell number?");
  135. }
  136. while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index))
  137. {
  138. mod_index++;
  139. }
  140. return mod_index;
  141. }
  142. #endif /* __LP64__ */
  143. static int do_newer_workstation_inventory(void)
  144. {
  145. long status;
  146. int i, num = 0;
  147. /* So the idea here is to simply try one SYSTEM_MAP call.  If 
  148.    that one works, great, otherwise do it another way */
  149. status = pdc_system_map_find_mods(&module_result,&module_path,0);
  150. if (status == PDC_RET_OK) {
  151. /* This is for newer non-PDC-PAT boxes */
  152. printk("a newer box...n");
  153. for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC && 
  154. status != PDC_RET_NE_MOD ;i++) {
  155. status = pdc_system_map_find_mods(&module_result,&module_path,i);
  156. if (status == PDC_RET_OK) {
  157. num++;
  158. register_module(module_result.mod_addr);
  159. }
  160. }
  161. }
  162. return (num > 0);
  163. }
  164. #ifndef __LP64__
  165. static struct  pdc_memory_map r_addr __attribute__ ((aligned (8)));
  166. static int really_do_oldhw_inventory(void)
  167. {
  168. int i, mod, num = 0;
  169. int status;
  170. unsigned int hw_type;
  171. unsigned int func;
  172. /* This is undocumented at the time of writing, but basically 
  173.    we're setting up mod_path so that bc[0..4]=0xff, and step
  174.    through mod to get the "Path Structure for GSC Modules".  If
  175.    it works, use the returned HPA and determine the hardware type.  */
  176. for (i=0;i<6;i++) module_path.bc[i]=0xff;
  177. for (mod=0;mod<16;mod++) {
  178. char *stype = NULL;
  179. module_path.mod=mod;
  180. status = pdc_mem_map_hpa(&r_addr, &module_path);
  181. if (status!=PDC_RET_OK) continue;
  182. status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa,
  183. 0, &iodc_data,32 );
  184. if (status!=PDC_RET_OK) continue;
  185. hw_type = iodc_data[3]&0x1f;
  186. switch (hw_type)
  187. {
  188. case HPHW_NPROC: /* 0 */
  189. stype="Processor"; break;
  190. case HPHW_MEMORY: /* 1 */
  191. stype="Memory"; break;
  192. case HPHW_B_DMA: /* 2 */
  193. stype="Type B DMA"; break;
  194. case HPHW_A_DMA: /* 4 */
  195. stype="Type A DMA"; break;
  196. case HPHW_A_DIRECT: /* 5 */
  197. stype="Type A Direct"; break;
  198. case HPHW_BCPORT: /* 7 */
  199. stype="Bus Converter Port"; break;
  200. case HPHW_CONSOLE: /* 9 */
  201. stype="Console"; break;
  202. case HPHW_FIO: /* 10 - Graphics */
  203. stype="Foreign I/O (Graphics)"; break;
  204. case HPHW_BA: /* 11 - Bus Adapter */
  205. stype="Bus Adapter"; break;
  206. case HPHW_IOA: /* 12 */
  207. stype="I/O Adapter"; break;
  208. case HPHW_BRIDGE: /* 13 */
  209. stype="Bridge"; break;
  210. case HPHW_FABRIC: /* 14 */
  211. stype="Fabric"; break;
  212. case HPHW_FAULTY: /* 31 */
  213. stype="Faulty HW"; break;
  214. case HPHW_OTHER: /* 42 */
  215. default:
  216. printk("Don't know this hw_type: %dn", hw_type);
  217. break;
  218. }
  219. // This is kluged. But don't want to replicate code for
  220. // most of the above cases.
  221. if (stype) {
  222. #ifdef DBG_PDC_QUERY
  223. // parisc/kernel/drivers.c
  224. extern int num_devices; 
  225. extern struct hp_device devices[];
  226. struct hp_hardware *h;
  227. #endif
  228. status = pdc_mem_map_hpa(&r_addr, &module_path);
  229. if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL)
  230. num++;
  231.     if (hw_type == HPHW_BA) {
  232. /* Now, we're checking for devices for each
  233.    module.  I seem to think that the
  234.    modules in question are Lasi (2), 2nd Lasi (6)
  235.    Wax (5).  To do this, set bc[5]=0, and set
  236.    bc[4] to the module, and step through the
  237.    functions. */
  238. for (i=0;i<4;i++) module_path.bc[i]=0xff;
  239. module_path.bc[4]=mod;
  240. for (func=0;func<16;func++) {
  241. module_path.mod = func;
  242. module_path.bc[5]=0;
  243. status = pdc_mem_map_hpa(&r_addr, &module_path);
  244. if (status!=PDC_RET_OK) continue;
  245. if (register_module((void *) r_addr.hpa) != NULL) 
  246. num++;
  247. }
  248. }
  249. // reset module_path.bc[]
  250. for (i=0;i<6;i++) module_path.bc[i]=0xff;
  251. #ifdef DBG_PDC_QUERY
  252. //
  253. // Let print_devices() dump everything which is registered.
  254. //
  255. h = devices[num_devices-1].reference;
  256. if (h) stype = h->name;
  257. printk("Found %s at %dn", stype, module_path.mod);
  258. #endif
  259. }
  260. }
  261. return num;
  262. }
  263. static int
  264. do_old_inventory(void)
  265. {
  266.         unsigned int bus_id;
  267. long status;
  268. int ok = 0;
  269. printk(" an older box...n");
  270. /* Here, we're going to check the model, and decide
  271.    if we should even bother trying. */
  272. status = pdc_model_info(&model);
  273. bus_id = (model.hversion >> (4+7) ) &0x1f;
  274. /* Here, we're checking the HVERSION of the CPU.
  275.    We're only checking the 0th CPU, since it'll
  276.    be the same on an SMP box. */
  277. switch (bus_id) {
  278. case 0x4:  /* 720, 730, 750, 735, 755 */
  279. case 0x6:  /* 705, 710 */
  280. case 0x7:  /* 715, 725 */
  281. case 0x8:  /* 745, 747, 742 */
  282. case 0xA:  /* 712 and similiar */
  283. case 0xC:  /* 715/64, at least */
  284. /* Do inventory using MEM_MAP */
  285. really_do_oldhw_inventory();
  286. ok = 1;
  287. break;
  288. default:  /* Everything else */
  289. printk("This is a very very old machine, with a bus_id of 0x%x.n",bus_id);
  290. panic("This will probably never run Linux.n");
  291. }
  292. return ok;
  293. }
  294. #endif /* !__LP64__ */
  295. void do_inventory(void){
  296. if((pdc_hpa_processor(&processor_hpa))<0){
  297. printk(KERN_INFO "Couldn't get the HPA of the processor.n" );
  298. }
  299. printk("Searching for devices in PDC firmware... ");
  300. printk("processor hpa 0x%lxn", processor_hpa.hpa);
  301. if (!(
  302. do_newer_workstation_inventory()
  303. #ifdef __LP64__
  304. || do_pat_inventory()
  305. #else /* __LP64__ */
  306. || do_old_inventory()
  307. #endif /* __LP64__ */
  308.     ))
  309. {
  310.     panic("I can't get the hardware inventory on this machine");
  311. }
  312. print_devices(NULL);
  313. }