File: /usr/src/linux/arch/ia64/sn/io/hubdev.c
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 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/iograph.h>
15 #include <asm/sn/sn1/hubdev.h>
16 #include <asm/sn/sn_private.h>
17 #include <asm/sn/invent.h>
18 #include <asm/sn/hcl.h>
19 #include <asm/sn/labelcl.h>
20
21 struct hubdev_callout {
22 int (*attach_method)(devfs_handle_t);
23 struct hubdev_callout *fp;
24 };
25
26 typedef struct hubdev_callout hubdev_callout_t;
27
28 mutex_t hubdev_callout_mutex;
29 hubdev_callout_t *hubdev_callout_list = NULL;
30
31 void
32 hubdev_init(void)
33 {
34 mutex_init(&hubdev_callout_mutex);
35 hubdev_callout_list = NULL;
36 }
37
38 void
39 hubdev_register(int (*attach_method)(devfs_handle_t))
40 {
41 hubdev_callout_t *callout;
42
43 ASSERT(attach_method);
44
45 callout = (hubdev_callout_t *)kmem_zalloc(sizeof(hubdev_callout_t), KM_SLEEP);
46 ASSERT(callout);
47
48 mutex_lock(&hubdev_callout_mutex);
49 /*
50 * Insert at the end of the list
51 */
52 callout->fp = hubdev_callout_list;
53 hubdev_callout_list = callout;
54 callout->attach_method = attach_method;
55 mutex_unlock(&hubdev_callout_mutex);
56 }
57
58 int
59 hubdev_unregister(int (*attach_method)(devfs_handle_t))
60 {
61 hubdev_callout_t **p;
62
63 ASSERT(attach_method);
64
65 mutex_lock(&hubdev_callout_mutex);
66 /*
67 * Remove registry element containing attach_method
68 */
69 for (p = &hubdev_callout_list; *p != NULL; p = &(*p)->fp) {
70 if ((*p)->attach_method == attach_method) {
71 hubdev_callout_t* victim = *p;
72 *p = (*p)->fp;
73 kfree(victim);
74 mutex_unlock(&hubdev_callout_mutex);
75 return (0);
76 }
77 }
78 mutex_unlock(&hubdev_callout_mutex);
79 return (ENOENT);
80 }
81
82
83 int
84 hubdev_docallouts(devfs_handle_t hub)
85 {
86 hubdev_callout_t *p;
87 int errcode;
88
89 mutex_lock(&hubdev_callout_mutex);
90
91 for (p = hubdev_callout_list; p != NULL; p = p->fp) {
92 ASSERT(p->attach_method);
93 errcode = (*p->attach_method)(hub);
94 if (errcode != 0) {
95 mutex_unlock(&hubdev_callout_mutex);
96 return (errcode);
97 }
98 }
99 mutex_unlock(&hubdev_callout_mutex);
100 return (0);
101 }
102
103 /*
104 * Given a hub vertex, return the base address of the Hspec space
105 * for that hub.
106 */
107 caddr_t
108 hubdev_prombase_get(devfs_handle_t hub)
109 {
110 hubinfo_t hinfo = NULL;
111
112 hubinfo_get(hub, &hinfo);
113 ASSERT(hinfo);
114
115 return ((caddr_t)NODE_RBOOT_BASE(hinfo->h_nasid));
116 }
117
118 cnodeid_t
119 hubdev_cnodeid_get(devfs_handle_t hub)
120 {
121 hubinfo_t hinfo = NULL;
122 hubinfo_get(hub, &hinfo);
123 ASSERT(hinfo);
124
125 return hinfo->h_cnodeid;
126 }
127