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