hb.c revision 1.21 1 1.21 thorpej /* $NetBSD: hb.c,v 1.21 2020/11/21 17:54:47 thorpej Exp $ */
2 1.13 lukem
3 1.13 lukem #include <sys/cdefs.h>
4 1.21 thorpej __KERNEL_RCSID(0, "$NetBSD: hb.c,v 1.21 2020/11/21 17:54:47 thorpej Exp $");
5 1.1 tsubai
6 1.19 matt #define __INTR_PRIVATE
7 1.1 tsubai #include <sys/param.h>
8 1.1 tsubai #include <sys/systm.h>
9 1.1 tsubai #include <sys/device.h>
10 1.21 thorpej #include <sys/kmem.h>
11 1.19 matt #include <sys/intr.h>
12 1.1 tsubai
13 1.1 tsubai #include <machine/autoconf.h>
14 1.1 tsubai
15 1.11 tsutsui #include <newsmips/dev/hbvar.h>
16 1.11 tsutsui
17 1.18 tsutsui #include "ioconf.h"
18 1.18 tsutsui
19 1.18 tsutsui static int hb_match(device_t, cfdata_t, void *);
20 1.18 tsutsui static void hb_attach(device_t, device_t, void *);
21 1.18 tsutsui static int hb_search(device_t, cfdata_t, const int *, void *);
22 1.14 tsutsui static int hb_print(void *, const char *);
23 1.1 tsubai
24 1.18 tsutsui CFATTACH_DECL_NEW(hb, 0,
25 1.9 thorpej hb_match, hb_attach, NULL, NULL);
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.18 tsutsui hb_match(device_t parent, cfdata_t 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.18 tsutsui hb_attach(device_t parent, device_t 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.18 tsutsui aprint_normal("\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.18 tsutsui hb_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
61 1.2 tsubai {
62 1.11 tsutsui struct hb_attach_args *ha = aux;
63 1.2 tsubai
64 1.11 tsutsui ha->ha_name = cf->cf_name;
65 1.11 tsutsui ha->ha_addr = cf->cf_addr;
66 1.11 tsutsui ha->ha_level = cf->cf_level;
67 1.2 tsubai
68 1.11 tsutsui if (config_match(parent, cf, ha) > 0)
69 1.11 tsutsui config_attach(parent, cf, ha, hb_print);
70 1.2 tsubai
71 1.2 tsubai return 0;
72 1.2 tsubai }
73 1.2 tsubai
74 1.1 tsubai /*
75 1.1 tsubai * Print out the confargs. The (parent) name is non-NULL
76 1.1 tsubai * when there was no match found by config_found().
77 1.1 tsubai */
78 1.1 tsubai static int
79 1.14 tsutsui hb_print(void *args, const char *name)
80 1.1 tsubai {
81 1.11 tsutsui struct hb_attach_args *ha = args;
82 1.1 tsubai
83 1.1 tsubai /* Be quiet about empty HB locations. */
84 1.1 tsubai if (name)
85 1.3 tsubai return QUIET;
86 1.1 tsubai
87 1.11 tsutsui if (ha->ha_addr != -1)
88 1.11 tsutsui aprint_normal(" addr 0x%x", ha->ha_addr);
89 1.1 tsubai
90 1.3 tsubai return UNCONF;
91 1.4 tsubai }
92 1.4 tsubai
93 1.4 tsubai void *
94 1.14 tsutsui hb_intr_establish(int level, int mask, int priority, int (*func)(void *),
95 1.14 tsutsui void *arg)
96 1.4 tsubai {
97 1.12 tsutsui struct newsmips_intr *ip;
98 1.12 tsutsui struct newsmips_intrhand *ih, *curih;
99 1.12 tsutsui
100 1.12 tsutsui ip = &hbintr_tab[level];
101 1.4 tsubai
102 1.21 thorpej ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
103 1.12 tsutsui ih->ih_func = func;
104 1.12 tsutsui ih->ih_arg = arg;
105 1.12 tsutsui ih->ih_level = level;
106 1.12 tsutsui ih->ih_mask = mask;
107 1.12 tsutsui ih->ih_priority = priority;
108 1.12 tsutsui
109 1.12 tsutsui if (LIST_EMPTY(&ip->intr_q)) {
110 1.12 tsutsui LIST_INSERT_HEAD(&ip->intr_q, ih, ih_q);
111 1.12 tsutsui goto done;
112 1.4 tsubai }
113 1.4 tsubai
114 1.12 tsutsui for (curih = LIST_FIRST(&ip->intr_q);
115 1.12 tsutsui LIST_NEXT(curih, ih_q) != NULL;
116 1.12 tsutsui curih = LIST_NEXT(curih, ih_q)) {
117 1.12 tsutsui if (ih->ih_priority > curih->ih_priority) {
118 1.12 tsutsui LIST_INSERT_BEFORE(curih, ih, ih_q);
119 1.12 tsutsui goto done;
120 1.4 tsubai }
121 1.4 tsubai }
122 1.4 tsubai
123 1.12 tsutsui LIST_INSERT_AFTER(curih, ih, ih_q);
124 1.12 tsutsui
125 1.12 tsutsui done:
126 1.4 tsubai return ih;
127 1.4 tsubai }
128 1.4 tsubai
129 1.4 tsubai void
130 1.14 tsutsui hb_intr_dispatch(int level, int stat)
131 1.12 tsutsui {
132 1.12 tsutsui struct newsmips_intr *ip;
133 1.12 tsutsui struct newsmips_intrhand *ih;
134 1.12 tsutsui
135 1.12 tsutsui ip = &hbintr_tab[level];
136 1.12 tsutsui
137 1.12 tsutsui LIST_FOREACH(ih, &ip->intr_q, ih_q) {
138 1.12 tsutsui if (ih->ih_mask & stat)
139 1.12 tsutsui (*ih->ih_func)(ih->ih_arg);
140 1.4 tsubai }
141 1.1 tsubai }
142