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