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