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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id$
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
  8.  * Copyright (C) 2000 by Colin Ngam
  9.  */
  10. /*
  11.  * hubspc.c - Hub Memory Space Management Driver
  12.  * This driver implements the managers for the following
  13.  * memory resources:
  14.  * 1) reference counters
  15.  */
  16. #include <linux/types.h>
  17. #include <linux/config.h>
  18. #include <linux/slab.h>
  19. #include <asm/sn/sgi.h>
  20. #include <linux/devfs_fs.h>
  21. #include <linux/devfs_fs_kernel.h>
  22. #include <asm/io.h>
  23. #include <asm/sn/iograph.h>
  24. #include <asm/sn/invent.h>
  25. #include <asm/sn/hcl.h>
  26. #include <asm/sn/labelcl.h>
  27. #include <asm/sn/mem_refcnt.h>
  28. #include <asm/sn/agent.h>
  29. #include <asm/sn/addrs.h>
  30. #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
  31. #include <asm/sn/sn1/ip27config.h>
  32. #include <asm/sn/sn1/hubdev.h>
  33. #include <asm/sn/ksys/elsc.h>
  34. #endif
  35. #include <asm/sn/hubspc.h>
  36. /* Uncomment the following line for tracing */
  37. /* #define HUBSPC_DEBUG 1 */
  38. int hubspc_devflag = D_MP;
  39. extern void *device_info_get(devfs_handle_t device);
  40. extern void device_info_set(devfs_handle_t device, void *info);
  41. /***********************************************************************/
  42. /* CPU Prom Space         */
  43. /***********************************************************************/
  44. typedef struct cpuprom_info {
  45. devfs_handle_t prom_dev;
  46. devfs_handle_t nodevrtx;
  47. struct cpuprom_info *next;
  48. }cpuprom_info_t;
  49. static cpuprom_info_t *cpuprom_head;
  50. static spinlock_t cpuprom_spinlock;
  51. #define PROM_LOCK() mutex_spinlock(&cpuprom_spinlock)
  52. #define PROM_UNLOCK(s) mutex_spinunlock(&cpuprom_spinlock, (s))
  53. /*
  54.  * Add prominfo to the linked list maintained.
  55.  */
  56. void
  57. prominfo_add(devfs_handle_t hub, devfs_handle_t prom)
  58. {
  59. cpuprom_info_t *info;
  60. unsigned long s;
  61. info = kmalloc(sizeof(cpuprom_info_t), GFP_KERNEL);
  62. ASSERT(info);
  63. info->prom_dev = prom;
  64. info->nodevrtx = hub;
  65. s = PROM_LOCK();
  66. info->next = cpuprom_head;
  67. cpuprom_head = info;
  68. PROM_UNLOCK(s);
  69. }
  70. void
  71. prominfo_del(devfs_handle_t prom)
  72. {
  73. unsigned long s;
  74. cpuprom_info_t *info;
  75. cpuprom_info_t **prev;
  76. s = PROM_LOCK();
  77. prev = &cpuprom_head;
  78. while ( (info = *prev) ) {
  79. if (info->prom_dev == prom) {
  80. *prev = info->next;
  81. PROM_UNLOCK(s);
  82. return;
  83. }
  84. prev = &info->next;
  85. }
  86. PROM_UNLOCK(s);
  87. ASSERT(0);
  88. }
  89. devfs_handle_t
  90. prominfo_nodeget(devfs_handle_t prom)
  91. {
  92. unsigned long s;
  93. cpuprom_info_t *info;
  94. s = PROM_LOCK();
  95. info = cpuprom_head;
  96. while (info) {
  97. if(info->prom_dev == prom) {
  98. PROM_UNLOCK(s);
  99. return info->nodevrtx;
  100. }
  101. info = info->next;
  102. }
  103. PROM_UNLOCK(s);
  104. return 0;
  105. }
  106. #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
  107. #define SN_PROMVERSION INV_IP35PROM
  108. #endif
  109. /* Add "detailed" labelled inventory information to the
  110.  * prom vertex 
  111.  */
  112. void
  113. cpuprom_detailed_inventory_info_add(devfs_handle_t prom_dev,devfs_handle_t node)
  114. {
  115. invent_miscinfo_t  *cpuprom_inventory_info;
  116. extern invent_generic_t *klhwg_invent_alloc(cnodeid_t cnode, 
  117.      int class, int size);
  118. cnodeid_t cnode = hubdev_cnodeid_get(node);
  119. /* Allocate memory for the extra inventory information
  120.  * for the  prom
  121.  */
  122. cpuprom_inventory_info = (invent_miscinfo_t *) 
  123. klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
  124. ASSERT(cpuprom_inventory_info);
  125. /* Set the enabled flag so that the hinv interprets this
  126.  * information
  127.  */
  128. cpuprom_inventory_info->im_gen.ig_flag = INVENT_ENABLED;
  129. cpuprom_inventory_info->im_type = SN_PROMVERSION;
  130. /* Store prom revision into inventory information */
  131. cpuprom_inventory_info->im_rev = IP27CONFIG.pvers_rev;
  132. cpuprom_inventory_info->im_version = IP27CONFIG.pvers_vers;
  133. /* Store this info as labelled information hanging off the
  134.  * prom device vertex
  135.  */
  136. hwgraph_info_add_LBL(prom_dev, INFO_LBL_DETAIL_INVENT, 
  137.      (arbitrary_info_t) cpuprom_inventory_info);
  138. /* Export this information so that user programs can get to
  139.  * this by using attr_get()
  140.  */
  141.         hwgraph_info_export_LBL(prom_dev, INFO_LBL_DETAIL_INVENT,
  142. sizeof(invent_miscinfo_t));
  143. }
  144. int
  145. cpuprom_attach(devfs_handle_t node)
  146. {
  147.         devfs_handle_t prom_dev;
  148.         hwgraph_char_device_add(node, EDGE_LBL_PROM, "hubspc_", &prom_dev);
  149. #ifdef HUBSPC_DEBUG
  150. printf("hubspc: prom_attach hub: 0x%x prom: 0x%xn", node, prom_dev);
  151. #endif /* HUBSPC_DEBUG */
  152. device_inventory_add(prom_dev, INV_PROM, SN_PROMVERSION,
  153. (major_t)0, (minor_t)0, 0);
  154. /* Add additional inventory info about the cpu prom like
  155.  * revision & version numbers etc.
  156.  */
  157. cpuprom_detailed_inventory_info_add(prom_dev,node);
  158.         device_info_set(prom_dev, (void*)(ulong)HUBSPC_PROM);
  159. prominfo_add(node, prom_dev);
  160.         return (0);
  161. }
  162. #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
  163. #define FPROM_CONFIG_ADDR MD_JUNK_BUS_TIMING
  164. #define FPROM_ENABLE_MASK MJT_FPROM_ENABLE_MASK
  165. #define FPROM_ENABLE_SHFT MJT_FPROM_ENABLE_SHFT
  166. #define FPROM_SETUP_MASK MJT_FPROM_SETUP_MASK
  167. #define FPROM_SETUP_SHFT MJT_FPROM_SETUP_SHFT
  168. #endif
  169. /*ARGSUSED*/
  170. int
  171. cpuprom_map(devfs_handle_t dev, vhandl_t *vt, off_t addr, size_t len)
  172. {
  173.         int  errcode;
  174. caddr_t  kvaddr;
  175. devfs_handle_t node;
  176. cnodeid_t  cnode;
  177. node = prominfo_nodeget(dev);
  178. if (!node)
  179. return EIO;
  180.         
  181. kvaddr = hubdev_prombase_get(node);
  182. cnode  = hubdev_cnodeid_get(node);
  183. #ifdef HUBSPC_DEBUG
  184. printf("cpuprom_map: hubnode %d kvaddr 0x%xn", node, kvaddr);
  185. #endif
  186. if (len > RBOOT_SIZE)
  187. len = RBOOT_SIZE;
  188.         /*
  189.          * Map in the prom space
  190.          */
  191. errcode = v_mapphys(vt, kvaddr, len);
  192. if (errcode == 0 ){
  193. /*
  194.  * Set the MD configuration registers suitably.
  195.  */
  196. nasid_t nasid;
  197. uint64_t value;
  198. volatile hubreg_t *regaddr;
  199. nasid = COMPACT_TO_NASID_NODEID(cnode);
  200. regaddr = REMOTE_HUB_ADDR(nasid, FPROM_CONFIG_ADDR);
  201. value = HUB_L(regaddr);
  202. value &= ~(FPROM_SETUP_MASK | FPROM_ENABLE_MASK);
  203. {
  204. value |= (((long)CONFIG_FPROM_SETUP << FPROM_SETUP_SHFT) | 
  205.   ((long)CONFIG_FPROM_ENABLE << FPROM_ENABLE_SHFT));
  206. }
  207. HUB_S(regaddr, value);
  208. }
  209.         return (errcode);
  210. }
  211. /*ARGSUSED*/
  212. int
  213. cpuprom_unmap(devfs_handle_t dev, vhandl_t *vt)
  214. {
  215.         return 0;
  216. }
  217. /***********************************************************************/
  218. /* Base Hub Space Driver                                               */
  219. /***********************************************************************/
  220. // extern int l1_attach( devfs_handle_t );
  221. /*
  222.  * hubspc_init
  223.  * Registration of the hubspc devices with the hub manager
  224.  */
  225. void
  226. hubspc_init(void)
  227. {
  228.         /*
  229.          * Register with the hub manager
  230.          */
  231.         /* The reference counters */
  232.         hubdev_register(mem_refcnt_attach);
  233. /* Prom space */
  234. hubdev_register(cpuprom_attach);
  235. #if defined(CONFIG_SERIAL_SGI_L1_PROTOCOL)
  236. /* L1 system controller link */
  237. if ( !IS_RUNNING_ON_SIMULATOR() ) {
  238. /* initialize the L1 link */
  239. void l1_cons_init( l1sc_t *sc );
  240. elsc_t *get_elsc(void);
  241. l1_cons_init((l1sc_t *)get_elsc());
  242. }
  243. #endif
  244. #ifdef HUBSPC_DEBUG
  245. printf("hubspc_init: Completedn");
  246. #endif /* HUBSPC_DEBUG */
  247. /* Initialize spinlocks */
  248. mutex_spinlock_init(&cpuprom_spinlock);
  249. }
  250. /* ARGSUSED */
  251. int
  252. hubspc_open(devfs_handle_t *devp, mode_t oflag, int otyp, cred_t *crp)
  253. {
  254.         int errcode = 0;
  255.         
  256.         switch ((hubspc_subdevice_t)(ulong)device_info_get(*devp)) {
  257.         case HUBSPC_REFCOUNTERS:
  258.                 errcode = mem_refcnt_open(devp, oflag, otyp, crp);
  259.                 break;
  260.         case HUBSPC_PROM:
  261.                 break;
  262.         default:
  263.                 errcode = ENODEV;
  264.         }
  265. #ifdef HUBSPC_DEBUG
  266. printf("hubspc_open: Completed open for type %dn",
  267.                (hubspc_subdevice_t)(ulong)device_info_get(*devp));
  268. #endif /* HUBSPC_DEBUG */
  269.         return (errcode);
  270. }
  271. /* ARGSUSED */
  272. int
  273. hubspc_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp)
  274. {
  275.         int errcode = 0;
  276.         
  277.         switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) {
  278.         case HUBSPC_REFCOUNTERS:
  279.                 errcode = mem_refcnt_close(dev, oflag, otyp, crp);
  280.                 break;
  281.         case HUBSPC_PROM:
  282.                 break;
  283.         default:
  284.                 errcode = ENODEV;
  285.         }
  286. #ifdef HUBSPC_DEBUG
  287. printf("hubspc_close: Completed close for type %dn",
  288.                (hubspc_subdevice_t)(ulong)device_info_get(dev));
  289. #endif /* HUBSPC_DEBUG */
  290.         return (errcode);
  291. }
  292. /* ARGSUSED */
  293. int
  294. hubspc_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot)
  295. {
  296. /*REFERENCED*/
  297.         hubspc_subdevice_t subdevice;
  298.         int errcode = 0;
  299. /* check validity of request */
  300. if( len == 0 ) {
  301. return ENXIO;
  302.         }
  303.         subdevice = (hubspc_subdevice_t)(ulong)device_info_get(dev);
  304. #ifdef HUBSPC_DEBUG
  305. printf("hubspc_map: subdevice: %d vaddr: 0x%x phyaddr: 0x%x len: 0x%xn",
  306.        subdevice, v_getaddr(vt), off, len);
  307. #endif /* HUBSPC_DEBUG */
  308.         switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) {
  309.         case HUBSPC_REFCOUNTERS:
  310.                 errcode = mem_refcnt_mmap(dev, vt, off, len, prot);
  311.                 break;
  312.         case HUBSPC_PROM:
  313. errcode = cpuprom_map(dev, vt, off, len);
  314.                 break;
  315.         default:
  316.                 errcode = ENODEV;
  317.         }
  318. #ifdef HUBSPC_DEBUG
  319. printf("hubspc_map finished: spctype: %d vaddr: 0x%x len: 0x%xn",
  320.        (hubspc_subdevice_t)(ulong)device_info_get(dev), v_getaddr(vt), len);
  321. #endif /* HUBSPC_DEBUG */
  322. return errcode;
  323. }
  324. /* ARGSUSED */
  325. int
  326. hubspc_unmap(devfs_handle_t dev, vhandl_t *vt)
  327. {
  328.         int errcode = 0;
  329.         
  330.         switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) {
  331.         case HUBSPC_REFCOUNTERS:
  332.                 errcode = mem_refcnt_unmap(dev, vt);
  333.                 break;
  334.         case HUBSPC_PROM:
  335.                 errcode = cpuprom_unmap(dev, vt);
  336.                 break;
  337.         default:
  338.                 errcode = ENODEV;
  339.         }
  340. return errcode;
  341. }
  342. /* ARGSUSED */
  343. int
  344. hubspc_ioctl(devfs_handle_t dev,
  345.              int cmd,
  346.              void *arg,
  347.              int mode,
  348.              cred_t *cred_p,
  349.              int *rvalp)
  350. {
  351.         int errcode = 0;
  352.         
  353.         switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) {
  354.         case HUBSPC_REFCOUNTERS:
  355.                 errcode = mem_refcnt_ioctl(dev, cmd, arg, mode, cred_p, rvalp);
  356.                 break;
  357.         case HUBSPC_PROM:
  358.                 break;
  359.         default:
  360.                 errcode = ENODEV;
  361.         }
  362. return errcode;
  363. }