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