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