1 1.23 thorpej /* $NetBSD: hb.c,v 1.23 2021/08/07 16:19:01 thorpej Exp $ */ 2 1.13 lukem 3 1.13 lukem #include <sys/cdefs.h> 4 1.23 thorpej __KERNEL_RCSID(0, "$NetBSD: hb.c,v 1.23 2021/08/07 16:19:01 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.22 thorpej config_search(self, &ha, 57 1.23 thorpej CFARGS(.search = hb_search)); 58 1.1 tsubai } 59 1.1 tsubai 60 1.2 tsubai static int 61 1.18 tsutsui hb_search(device_t parent, cfdata_t cf, const int *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.22 thorpej if (config_probe(parent, cf, ha)) 70 1.23 thorpej config_attach(parent, cf, ha, hb_print, CFARGS_NONE); 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.21 thorpej ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 104 1.12 tsutsui ih->ih_func = func; 105 1.12 tsutsui ih->ih_arg = arg; 106 1.12 tsutsui ih->ih_level = level; 107 1.12 tsutsui ih->ih_mask = mask; 108 1.12 tsutsui ih->ih_priority = priority; 109 1.12 tsutsui 110 1.12 tsutsui if (LIST_EMPTY(&ip->intr_q)) { 111 1.12 tsutsui LIST_INSERT_HEAD(&ip->intr_q, ih, ih_q); 112 1.12 tsutsui goto done; 113 1.4 tsubai } 114 1.4 tsubai 115 1.12 tsutsui for (curih = LIST_FIRST(&ip->intr_q); 116 1.12 tsutsui LIST_NEXT(curih, ih_q) != NULL; 117 1.12 tsutsui curih = LIST_NEXT(curih, ih_q)) { 118 1.12 tsutsui if (ih->ih_priority > curih->ih_priority) { 119 1.12 tsutsui LIST_INSERT_BEFORE(curih, ih, ih_q); 120 1.12 tsutsui goto done; 121 1.4 tsubai } 122 1.4 tsubai } 123 1.4 tsubai 124 1.12 tsutsui LIST_INSERT_AFTER(curih, ih, ih_q); 125 1.12 tsutsui 126 1.12 tsutsui done: 127 1.4 tsubai return ih; 128 1.4 tsubai } 129 1.4 tsubai 130 1.4 tsubai void 131 1.14 tsutsui hb_intr_dispatch(int level, int stat) 132 1.12 tsutsui { 133 1.12 tsutsui struct newsmips_intr *ip; 134 1.12 tsutsui struct newsmips_intrhand *ih; 135 1.12 tsutsui 136 1.12 tsutsui ip = &hbintr_tab[level]; 137 1.12 tsutsui 138 1.12 tsutsui LIST_FOREACH(ih, &ip->intr_q, ih_q) { 139 1.12 tsutsui if (ih->ih_mask & stat) 140 1.12 tsutsui (*ih->ih_func)(ih->ih_arg); 141 1.4 tsubai } 142 1.1 tsubai } 143