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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* arch/parisc/kernel/pdc.c  - safe pdc access routines
  2.  *
  3.  * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
  4.  * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
  5.  *
  6.  * only these routines should be used out of the real kernel (i.e. everything
  7.  * using virtual addresses) for obvious reasons */
  8. /* I think it would be in everyone's best interest to follow this
  9.  * guidelines when writing PDC wrappers:
  10.  *
  11.  *  - the name of the pdc wrapper should match one of the macros
  12.  *    used for the first two arguments
  13.  *  - don't use caps for random parts of the name
  14.  *  - use ASSERT_ALIGN to ensure the aligment of the arguments is
  15.  *    correct
  16.  *  - use __pa() to convert virtual (kernel) pointers to physical
  17.  *    ones.
  18.  *  - the name of the struct used for pdc return values should equal
  19.  *    one of the macros used for the first two arguments to the
  20.  *    corresponding PDC call
  21.  *  - keep the order of arguments
  22.  *  - don't be smart (setting trailing NUL bytes for strings, return
  23.  *    something useful even if the call failed) unless you are sure
  24.  *    it's not going to affect functionality or performance
  25.  *
  26.  * Example:
  27.  * int pdc_cache_info(struct pdc_cache_info *cache_info )
  28.  * {
  29.  * ASSERT_ALIGN(cache_info, 8);
  30.  *
  31.  * return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
  32.  * }
  33.  * prumpf 991016
  34.  */
  35. #include <linux/kernel.h>
  36. #include <linux/string.h>
  37. #include <asm/page.h>
  38. #include <asm/pdc.h>
  39. #include <asm/real.h>
  40. #include <asm/system.h>
  41. #define ASSERT_ALIGN(ptr, align)
  42. do { if(((unsigned long)(ptr)) & (align-1)) {
  43. printk("PDC: %s:%d  %s() called with "
  44. "unaligned argument from %p", __FILE__, __LINE__, 
  45. __FUNCTION__, __builtin_return_address(0));
  46. return -1;
  47. } } while(0)
  48. /* verify address can be accessed without an HPMC */
  49. int pdc_add_valid(void *address)
  50. {
  51. ASSERT_ALIGN(address, 4);
  52. return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address);
  53. }
  54. #if 0
  55. int pdc_chassis_warn(struct pdc_chassis_warn *address)
  56. {
  57. ASSERT_ALIGN(address, 4);
  58. return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0);
  59. }
  60. #endif
  61. int pdc_chassis_disp(unsigned long disp)
  62. {
  63. return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
  64. }
  65. int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len)
  66. {
  67. ASSERT_ALIGN(pdc_result, 4);
  68. ASSERT_ALIGN(chassis_info, 4);
  69. return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO, 
  70.         __pa(pdc_result), __pa(chassis_info), len);
  71. }
  72. int pdc_hpa_processor(void *address)
  73. {
  74. /* We're using 0 for the last parameter just to make sure.
  75.    It's actually HVERSION dependant.  And remember, life is
  76.    hard without a backspace. */
  77. ASSERT_ALIGN(address, 4);
  78. return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0);
  79. }
  80. #if 0
  81. int pdc_hpa_modules(void *address)
  82. {
  83. return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address);
  84. }
  85. #endif
  86. int pdc_iodc_read(void *address, void * hpa, unsigned int index,
  87. void * iodc_data, unsigned int iodc_data_size)
  88. {
  89. ASSERT_ALIGN(address, 4);
  90. ASSERT_ALIGN(iodc_data, 8);
  91. return mem_pdc_call(PDC_IODC, PDC_IODC_READ, 
  92. __pa(address), hpa, index, __pa(iodc_data), iodc_data_size);
  93. }
  94. int pdc_system_map_find_mods(void *pdc_mod_info, 
  95. void *mod_path, int index)
  96. {
  97. return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE,
  98. __pa(pdc_mod_info), __pa(mod_path), (long)index);
  99. }
  100. int pdc_model_info(struct pdc_model *model) {
  101. ASSERT_ALIGN(model, 8);
  102. return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0);
  103. }
  104. /* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */ 
  105. int pdc_model_sysmodel(char * name)
  106. {
  107. struct pdc_model_sysmodel sys_model;
  108. int retval;
  109. ASSERT_ALIGN(&sys_model, 8);
  110. ASSERT_ALIGN(name, 4);
  111. sys_model.mod_len = 0;
  112. retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model),
  113.     OS_ID_HPUX,__pa(name));
  114. if (retval == PDC_RET_OK) 
  115.     name[sys_model.mod_len] = ''; /* add trailing '' */
  116. else
  117.     name[0] = 0;
  118. return retval;
  119. }
  120. /* id: 0 = cpu revision, 1 = boot-rom-version */
  121. int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) {
  122. return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id);
  123. }
  124. int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) {
  125. cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */
  126. return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0);  /* 6="return CPU ID" */
  127. }
  128. int pdc_cache_info(struct pdc_cache_info *cache_info) {
  129. ASSERT_ALIGN(cache_info, 8);
  130. return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
  131. }
  132. #ifndef __LP64__
  133. int pdc_btlb_info( struct pdc_btlb_info *btlb ) {
  134. int status;
  135. status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0);
  136. if (status<0) btlb->max_size = 0;
  137. return status;
  138. }
  139. int pdc_mem_map_hpa(void *r_addr, void *mod_path) {
  140. return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA,
  141. __pa(r_addr),__pa(mod_path));
  142. }
  143. int pdc_lan_station_id(char *lan_addr, void *net_hpa) {
  144. struct pdc_lan_station_id id;
  145. unsigned char *addr;
  146. if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
  147. __pa(&id), net_hpa) < 0)
  148. addr = 0; /* FIXME: else read MAC from NVRAM */
  149.     else
  150. addr = id.addr;
  151. if (addr)
  152. memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE);
  153.     else
  154. memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
  155. return (addr != 0);
  156. }
  157. #endif
  158. /* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */
  159. int pdc_pci_irt_size(void *r_addr, void *hpa)
  160. {
  161. return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
  162. __pa(r_addr), hpa);
  163. }
  164. int pdc_pci_irt(void *r_addr, void *hpa, void *tbl)
  165. {
  166. return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
  167. __pa(r_addr), hpa, __pa(tbl));
  168. }
  169. /* access the TOD clock */
  170. int pdc_tod_read(struct pdc_tod *tod)
  171. {
  172. ASSERT_ALIGN(tod, 8);
  173. return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0);
  174. }
  175. int pdc_tod_set(unsigned long sec, unsigned long usec)
  176. {
  177. return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
  178. }