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