xref: /netbsd/sys/dev/hpc/hpcioman.c (revision c4a72b64)
1 /*	$NetBSD: hpcioman.c,v 1.9 2002/10/02 16:33:50 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: hpcioman.c,v 1.9 2002/10/02 16:33:50 thorpej Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 
46 #include <machine/config_hook.h>
47 #include <machine/platid.h>
48 #include <machine/platid_mask.h>
49 
50 #include <machine/bus.h>
51 #include <dev/hpc/hpciovar.h>
52 #include <dev/hpc/hpciomanvar.h>
53 
54 #include "locators.h"
55 
56 int	hpcioman_match(struct device *, struct cfdata *, void *);
57 void	hpcioman_attach(struct device *, struct device *, void *);
58 int	hpcioman_print(void *, const char *);
59 int	hpcioman_search(struct device *, struct cfdata *, void *);
60 
61 struct hpcioman_softc {
62 	struct device sc_dev;
63 };
64 
65 CFATTACH_DECL(hpcioman, sizeof(struct hpcioman_softc),
66     hpcioman_match, hpcioman_attach, NULL, NULL);
67 
68 int
69 hpcioman_match(struct device *parent, struct cfdata *cf, void *aux)
70 {
71 	struct hpcio_attach_args *haa = aux;
72 	platid_mask_t mask;
73 
74 	if (strcmp(haa->haa_busname, HPCIO_BUSNAME))
75 		return (0);
76 	/* select platform */
77 	mask = PLATID_DEREF(cf->cf_loc[HPCIOIFCF_PLATFORM]);
78 
79 	return (platid_match(&platid, &mask));
80 }
81 
82 void
83 hpcioman_attach(struct device *parent, struct device *self, void *aux)
84 {
85 	printf("\n");
86 
87 	config_search(hpcioman_search, self, aux);
88 }
89 
90 int
91 hpcioman_search(struct device *parent, struct cfdata *cf, void *aux)
92 {
93 	//struct hpcioman_softc *sc = (struct hpcioman_softc *)parent;
94 	struct hpcio_attach_args *haa = aux;
95 	struct hpcioman_attach_args hma;
96 
97 	/* get io chip */
98 	hma.hma_hc = (*haa->haa_getchip)(haa->haa_sc, cf->cf_iochip);
99 
100 	/* interrupt mode */
101 	if (cf->cf_level != HPCIOMANCF_LEVEL_DEFAULT) {
102 		switch (cf->cf_hold) {
103 		case 1:
104 			hma.hma_intr_mode = HPCIO_INTR_HOLD;
105 			break;
106 		case 0:
107 		case HPCIOMANCF_HOLD_DEFAULT:
108 		default:
109 			hma.hma_intr_mode = HPCIO_INTR_THROUGH;
110 			break;
111 		}
112 		hma.hma_intr_mode |= HPCIO_INTR_LEVEL;
113 		if (cf->cf_level == 0)
114 			hma.hma_intr_mode |= HPCIO_INTR_LOW;
115 		else
116 			hma.hma_intr_mode |= HPCIO_INTR_HIGH;
117 	} else {
118 		switch (cf->cf_hold) {
119 		case 0:
120 			hma.hma_intr_mode = HPCIO_INTR_THROUGH;
121 			break;
122 		case 1:
123 		case HPCIOMANCF_HOLD_DEFAULT:
124 		default:
125 			hma.hma_intr_mode = HPCIO_INTR_HOLD;
126 			break;
127 		}
128 		hma.hma_intr_mode |= HPCIO_INTR_EDGE;
129 		switch (cf->cf_edge) {
130 		case 1:
131 			hma.hma_intr_mode |= HPCIO_INTR_POSEDGE;
132 			break;
133 		case 2:
134 			hma.hma_intr_mode |= HPCIO_INTR_NEGEDGE;
135 			break;
136 		case 0:
137 		case 3:
138 		case HPCIOMANCF_EDGE_DEFAULT:
139 			hma.hma_intr_mode |= HPCIO_INTR_POSEDGE;
140 			hma.hma_intr_mode |= HPCIO_INTR_NEGEDGE;
141 			break;
142 		default:
143 			printf("%s(%d): invalid configuration, edge=%d",
144 			    __FILE__, __LINE__, cf->cf_edge);
145 			break;
146 		}
147 	}
148 
149 	hma.hma_type = cf->cf_type;
150 	hma.hma_id = cf->cf_id;
151 	hma.hma_port = cf->cf_port;
152 	if (cf->cf_active == 0) {
153 		hma.hma_on = 0;
154 		hma.hma_off = 1;
155 	} else {
156 		hma.hma_on = 1;
157 		hma.hma_off = 0;
158 	}
159 	hma.hma_initvalue = -1; /* none */
160 	if (cf->cf_initvalue != HPCIOMANCF_INITVALUE_DEFAULT) {
161 		if (cf->cf_initvalue == 0)
162 			hma.hma_initvalue = hma.hma_off;
163 		else
164 			hma.hma_initvalue = hma.hma_on;
165 	}
166 	hma.hma_connect = cf->cf_connect;
167 
168 	config_attach(parent, cf, &hma, hpcioman_print);
169 
170 	return (0);
171 }
172 
173 int
174 hpcioman_print(void *aux, const char *pnp)
175 {
176 	struct hpcioman_attach_args *hma = aux;
177 	int type = hma->hma_type;
178 
179 	if (!pnp)  {
180 		printf(" iochip %s, port %d, type %d, id %d",
181 		    hma->hma_hc ? hma->hma_hc->hc_name : "not found",
182 		    hma->hma_port, type, hma->hma_id);
183 		if (type == CONFIG_HOOK_BUTTONEVENT ||
184 		    type == CONFIG_HOOK_PMEVENT ||
185 		    type == CONFIG_HOOK_EVENT ||
186 		    type == CONFIG_HOOK_PCIINTR) {
187 			if (hma->hma_intr_mode & HPCIO_INTR_EDGE)
188 				printf (", interrupt edge [%s%s]",
189 				    (hma->hma_intr_mode&HPCIO_INTR_POSEDGE)
190 				    ? "p" : "",
191 				    (hma->hma_intr_mode&HPCIO_INTR_NEGEDGE)
192 				    ? "n" : "");
193 			else
194 				printf (", interrupt level %s",
195 				    (hma->hma_intr_mode&HPCIO_INTR_HIGH) ?
196 				    "high" : "low");
197 		}
198 		if (hma->hma_initvalue != -1)
199 			printf(", initial value %d", hma->hma_initvalue);
200 		if (hma->hma_on == 0)
201 			printf(", active low");
202 	}
203 
204 	return (QUIET);
205 }
206