hb.c revision 1.13 1 1.13 lukem /* $NetBSD: hb.c,v 1.13 2003/07/15 02:59:29 lukem Exp $ */
2 1.13 lukem
3 1.13 lukem #include <sys/cdefs.h>
4 1.13 lukem __KERNEL_RCSID(0, "$NetBSD: hb.c,v 1.13 2003/07/15 02:59:29 lukem Exp $");
5 1.1 tsubai
6 1.1 tsubai #include <sys/param.h>
7 1.1 tsubai #include <sys/systm.h>
8 1.1 tsubai #include <sys/device.h>
9 1.12 tsutsui #include <sys/malloc.h>
10 1.1 tsubai
11 1.1 tsubai #include <machine/autoconf.h>
12 1.12 tsutsui #include <machine/intr.h>
13 1.1 tsubai
14 1.11 tsutsui #include <newsmips/dev/hbvar.h>
15 1.11 tsutsui
16 1.1 tsubai static int hb_match __P((struct device *, struct cfdata *, void *));
17 1.1 tsubai static void hb_attach __P((struct device *, struct device *, void *));
18 1.2 tsubai static int hb_search __P((struct device *, struct cfdata *, void *));
19 1.1 tsubai static int hb_print __P((void *, const char *));
20 1.1 tsubai
21 1.9 thorpej CFATTACH_DECL(hb, sizeof(struct device),
22 1.9 thorpej hb_match, hb_attach, NULL, NULL);
23 1.1 tsubai
24 1.1 tsubai extern struct cfdriver hb_cd;
25 1.1 tsubai
26 1.12 tsutsui #define NLEVEL 4
27 1.12 tsutsui static struct newsmips_intr hbintr_tab[NLEVEL];
28 1.4 tsubai
29 1.1 tsubai static int
30 1.1 tsubai hb_match(parent, cf, aux)
31 1.1 tsubai struct device *parent;
32 1.1 tsubai struct cfdata *cf;
33 1.1 tsubai void *aux;
34 1.1 tsubai {
35 1.1 tsubai struct confargs *ca = aux;
36 1.1 tsubai
37 1.1 tsubai if (strcmp(ca->ca_name, hb_cd.cd_name) != 0)
38 1.1 tsubai return 0;
39 1.1 tsubai
40 1.1 tsubai return 1;
41 1.1 tsubai }
42 1.1 tsubai
43 1.1 tsubai static void
44 1.1 tsubai hb_attach(parent, self, aux)
45 1.1 tsubai struct device *parent;
46 1.1 tsubai struct device *self;
47 1.1 tsubai void *aux;
48 1.1 tsubai {
49 1.11 tsutsui struct hb_attach_args ha;
50 1.12 tsutsui struct newsmips_intr *ip;
51 1.12 tsutsui int i;
52 1.1 tsubai
53 1.1 tsubai printf("\n");
54 1.12 tsutsui
55 1.11 tsutsui memset(&ha, 0, sizeof(ha));
56 1.12 tsutsui for (i = 0; i < NLEVEL; i++) {
57 1.12 tsutsui ip = &hbintr_tab[i];
58 1.12 tsutsui LIST_INIT(&ip->intr_q);
59 1.12 tsutsui }
60 1.12 tsutsui
61 1.11 tsutsui config_search(hb_search, self, &ha);
62 1.1 tsubai }
63 1.1 tsubai
64 1.2 tsubai static int
65 1.2 tsubai hb_search(parent, cf, aux)
66 1.2 tsubai struct device *parent;
67 1.2 tsubai struct cfdata *cf;
68 1.2 tsubai void *aux;
69 1.2 tsubai {
70 1.11 tsutsui struct hb_attach_args *ha = aux;
71 1.2 tsubai
72 1.11 tsutsui ha->ha_name = cf->cf_name;
73 1.11 tsutsui ha->ha_addr = cf->cf_addr;
74 1.11 tsutsui ha->ha_level = cf->cf_level;
75 1.2 tsubai
76 1.11 tsutsui if (config_match(parent, cf, ha) > 0)
77 1.11 tsutsui config_attach(parent, cf, ha, hb_print);
78 1.2 tsubai
79 1.2 tsubai return 0;
80 1.2 tsubai }
81 1.2 tsubai
82 1.1 tsubai /*
83 1.1 tsubai * Print out the confargs. The (parent) name is non-NULL
84 1.1 tsubai * when there was no match found by config_found().
85 1.1 tsubai */
86 1.1 tsubai static int
87 1.1 tsubai hb_print(args, name)
88 1.1 tsubai void *args;
89 1.1 tsubai const char *name;
90 1.1 tsubai {
91 1.11 tsutsui struct hb_attach_args *ha = args;
92 1.1 tsubai
93 1.1 tsubai /* Be quiet about empty HB locations. */
94 1.1 tsubai if (name)
95 1.3 tsubai return QUIET;
96 1.1 tsubai
97 1.11 tsutsui if (ha->ha_addr != -1)
98 1.11 tsutsui aprint_normal(" addr 0x%x", ha->ha_addr);
99 1.1 tsubai
100 1.3 tsubai return UNCONF;
101 1.4 tsubai }
102 1.4 tsubai
103 1.4 tsubai void *
104 1.12 tsutsui hb_intr_establish(level, mask, priority, func, arg)
105 1.12 tsutsui int level, mask, priority;
106 1.4 tsubai int (*func) __P((void *));
107 1.4 tsubai void *arg;
108 1.4 tsubai {
109 1.12 tsutsui struct newsmips_intr *ip;
110 1.12 tsutsui struct newsmips_intrhand *ih, *curih;
111 1.12 tsutsui
112 1.12 tsutsui ip = &hbintr_tab[level];
113 1.4 tsubai
114 1.12 tsutsui ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
115 1.12 tsutsui if (ih == NULL)
116 1.12 tsutsui panic("hb_intr_establish: malloc failed");
117 1.12 tsutsui
118 1.12 tsutsui ih->ih_func = func;
119 1.12 tsutsui ih->ih_arg = arg;
120 1.12 tsutsui ih->ih_level = level;
121 1.12 tsutsui ih->ih_mask = mask;
122 1.12 tsutsui ih->ih_priority = priority;
123 1.12 tsutsui
124 1.12 tsutsui if (LIST_EMPTY(&ip->intr_q)) {
125 1.12 tsutsui LIST_INSERT_HEAD(&ip->intr_q, ih, ih_q);
126 1.12 tsutsui goto done;
127 1.4 tsubai }
128 1.4 tsubai
129 1.12 tsutsui for (curih = LIST_FIRST(&ip->intr_q);
130 1.12 tsutsui LIST_NEXT(curih, ih_q) != NULL;
131 1.12 tsutsui curih = LIST_NEXT(curih, ih_q)) {
132 1.12 tsutsui if (ih->ih_priority > curih->ih_priority) {
133 1.12 tsutsui LIST_INSERT_BEFORE(curih, ih, ih_q);
134 1.12 tsutsui goto done;
135 1.4 tsubai }
136 1.4 tsubai }
137 1.4 tsubai
138 1.12 tsutsui LIST_INSERT_AFTER(curih, ih, ih_q);
139 1.12 tsutsui
140 1.12 tsutsui done:
141 1.4 tsubai return ih;
142 1.4 tsubai }
143 1.4 tsubai
144 1.4 tsubai void
145 1.12 tsutsui hb_intr_dispatch(level, stat)
146 1.12 tsutsui int level;
147 1.12 tsutsui int stat;
148 1.12 tsutsui {
149 1.12 tsutsui struct newsmips_intr *ip;
150 1.12 tsutsui struct newsmips_intrhand *ih;
151 1.12 tsutsui
152 1.12 tsutsui ip = &hbintr_tab[level];
153 1.12 tsutsui
154 1.12 tsutsui LIST_FOREACH(ih, &ip->intr_q, ih_q) {
155 1.12 tsutsui if (ih->ih_mask & stat)
156 1.12 tsutsui (*ih->ih_func)(ih->ih_arg);
157 1.4 tsubai }
158 1.1 tsubai }
159