xref: /netbsd/sys/arch/x68k/x68k/autoconf.c (revision c4a72b64)
1 /*	$NetBSD: autoconf.c,v 1.37 2002/10/20 02:26:59 isaki Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Leo Weppelman
5  * Copyright (c) 1994 Christian E. Hopps
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Christian E. Hopps.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "opt_compat_netbsd.h"
34 #include "scsibus.h"
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/reboot.h>
39 #include <sys/conf.h>
40 #include <sys/device.h>
41 #include <sys/disk.h>
42 #include <sys/disklabel.h>
43 #include <sys/malloc.h>
44 #include <machine/cpu.h>
45 #include <x68k/x68k/iodevice.h>
46 #include <machine/bootinfo.h>
47 
48 #include <dev/scsipi/scsi_all.h>
49 #include <dev/scsipi/scsipi_all.h>
50 #include <dev/scsipi/scsiconf.h>
51 
52 void configure __P((void));
53 static void findroot __P((void));
54 void mbattach __P((struct device *, struct device *, void *));
55 int mbmatch __P((struct device *, struct cfdata*, void*));
56 int x68k_config_found __P((struct cfdata *, struct device *,
57 			   void *, cfprint_t));
58 
59 static struct device *scsi_find __P((dev_t));
60 static struct device *find_dev_byname __P((const char *));
61 
62 struct device *booted_device;
63 int booted_partition;
64 
65 int x68k_realconfig;
66 
67 #include <sys/kernel.h>
68 
69 /*
70  * called at boot time, configure all devices on system
71  */
72 void
73 cpu_configure()
74 {
75 	x68k_realconfig = 1;
76 
77 	if (config_rootfound("mainbus", "mainbus") == NULL)
78 		panic("no mainbus found");
79 
80 	/* Turn on interrupts */
81 	(void) spl0();
82 }
83 
84 void
85 cpu_rootconf()
86 {
87 	findroot();
88 
89 	printf("boot device: %s\n",
90 	    booted_device ? booted_device->dv_xname : "<unknown>");
91 
92 	setroot(booted_device, booted_partition);
93 }
94 
95 /*
96  * use config_search to find appropriate device, then call that device
97  * directly with NULL device variable storage.  A device can then
98  * always tell the difference between the real and console init
99  * by checking for NULL.
100  */
101 int
102 x68k_config_found(pcfp, pdp, auxp, pfn)
103 	struct cfdata *pcfp;
104 	struct device *pdp;
105 	void *auxp;
106 	cfprint_t pfn;
107 {
108 	struct device temp;
109 	struct cfdata *cf;
110 	const struct cfattach *ca;
111 
112 	if (x68k_realconfig)
113 		return(config_found(pdp, auxp, pfn) != NULL);
114 
115 	if (pdp == NULL)
116 		pdp = &temp;
117 
118 	/* XXX Emulate 'struct device' of mainbus for cfparent_match() */
119 	pdp->dv_cfdata = pcfp;
120 	pdp->dv_cfdriver = config_cfdriver_lookup(pcfp->cf_name);
121 	pdp->dv_unit = 0;
122 	if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
123 		ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
124 		if (ca != NULL) {
125 			(*ca->ca_attach)(pdp, NULL, auxp);
126 			pdp->dv_cfdata = NULL;
127 			return(1);
128 		}
129 	}
130 	pdp->dv_cfdata = NULL;
131 	return(0);
132 }
133 
134 /*
135  * this function needs to get enough configured to do a console
136  * basically this means start attaching the grfxx's that support
137  * the console. Kinda hacky but it works.
138  */
139 void
140 config_console()
141 {
142 	struct cfdata *cf;
143 
144 	config_init();
145 
146 	/*
147 	 * we need mainbus' cfdata.
148 	 */
149 	cf = config_rootsearch(NULL, "mainbus", "mainbus");
150 	if (cf == NULL)
151 		panic("no mainbus");
152 	x68k_config_found(cf, NULL, "intio", NULL);
153 	x68k_config_found(cf, NULL, "grfbus", NULL);
154 }
155 
156 dev_t	bootdev = 0;
157 struct device *booted_device;
158 
159 static void
160 findroot(void)
161 {
162 	int majdev, unit, part;
163 	const char *name;
164 	char buf[32];
165 
166 	if (booted_device)
167 		return;
168 
169 	if (boothowto & RB_ASKNAME)
170 		return;		/* Don't bother looking */
171 
172 	if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
173 		return;
174 
175 	majdev = B_TYPE(bootdev);
176 	if (X68K_BOOT_DEV_IS_SCSI(majdev)) {
177 		/*
178 		 * SCSI device
179 		 */
180 		if ((booted_device = scsi_find(bootdev)) != NULL)
181 			booted_partition = B_X68K_SCSI_PART(bootdev);
182 		return;
183 	}
184 	name = devsw_blk2name(majdev);
185 	if (name == NULL)
186 		return;
187 
188 	part = B_PARTITION(bootdev);
189 	unit = B_UNIT(bootdev);
190 
191 	sprintf(buf, "%s%d", name, unit);
192 
193 	if ((booted_device = find_dev_byname(buf)) != NULL)
194 		booted_partition = part;
195 }
196 
197 static const char *const name_netif[] = { X68K_BOOT_NETIF_STRINGS };
198 
199 void
200 device_register(dev, aux)
201 	struct device *dev;
202 	void *aux;
203 {
204 	int majdev;
205 	char tname[16];
206 
207 	/*
208 	 * Handle network interfaces here, the attachment information is
209 	 * not available driver independantly later.
210 	 * For disks, there is nothing useful available at attach time.
211 	 */
212 	if (dev->dv_class == DV_IFNET) {
213 		majdev = B_TYPE(bootdev);
214 		if (X68K_BOOT_DEV_IS_NETIF(majdev)) {
215 			sprintf(tname, "%s%d",
216 				name_netif[255 - majdev], B_UNIT(bootdev));
217 			if (!strcmp(tname, dev->dv_xname))
218 				goto found;
219 		}
220 	}
221 	return;
222 
223 found:
224 	if (booted_device) {
225 		/* XXX should be a "panic()" */
226 		printf("warning: double match for boot device (%s, %s)\n",
227 		       booted_device->dv_xname, dev->dv_xname);
228 		return;
229 	}
230 	booted_device = dev;
231 }
232 
233 static const char *const name_scsiif[] = { X68K_BOOT_SCSIIF_STRINGS };
234 
235 static struct device *
236 scsi_find(bdev)
237 	dev_t bdev;	/* encoded boot device */
238 {
239 #if defined(NSCSIBUS) && NSCSIBUS > 0
240 	int ifid;
241 	char tname[16];
242 	struct device *scsibus;
243 	struct scsibus_softc *sbsc;
244 	struct scsipi_periph *periph;
245 
246 	ifid = B_X68K_SCSI_IF(bdev);
247 	if (ifid >= sizeof name_scsiif/sizeof name_scsiif[0] ||
248 					!name_scsiif[ifid]) {
249 #if defined(COMPAT_09) || defined(COMPAT_10) || defined(COMPAT_11) ||	\
250     defined(COMPAT_12) || defined(COMPAT_13)
251 		/*
252 		 * old boot didn't pass interface type
253 		 * try "scsibus0"
254 		 */
255 		printf("warning: scsi_find: can't get boot interface -- "
256 		       "update boot loader\n");
257 		scsibus = find_dev_byname("scsibus0");
258 #else
259 		/* can't determine interface type */
260 		return NULL;
261 #endif
262 	} else {
263 		/*
264 		 * search for the scsibus whose parent is
265 		 * the specified SCSI interface
266 		 */
267 		sprintf(tname, "%s%d",
268 			name_scsiif[ifid], B_X68K_SCSI_IF_UN(bdev));
269 
270 		for (scsibus = TAILQ_FIRST(&alldevs); scsibus;
271 					scsibus = TAILQ_NEXT(scsibus, dv_list))
272 			if (scsibus->dv_parent
273 			    && !strcmp(tname, scsibus->dv_parent->dv_xname))
274 				break;
275 	}
276 	if (!scsibus)
277 		return NULL;
278 	sbsc = (struct scsibus_softc *) scsibus;
279 	periph = scsipi_lookup_periph(sbsc->sc_channel,
280 	    B_X68K_SCSI_ID(bdev), B_X68K_SCSI_LUN(bdev));
281 
282 	return periph ? periph->periph_dev : NULL;
283 #else
284 	return NULL;
285 #endif /* NSCSIBUS > 0 */
286 }
287 
288 /*
289  * Given a device name, find its struct device
290  * XXX - Move this to some common file?
291  */
292 static struct device *
293 find_dev_byname(name)
294 	const char *name;
295 {
296 	struct device *dv;
297 
298 	for (dv = TAILQ_FIRST(&alldevs); dv; dv = TAILQ_NEXT(dv, dv_list))
299 		if (!strcmp(dv->dv_xname, name))
300 			break;
301 
302 	return dv;
303 }
304 
305 /*
306  * mainbus driver
307  */
308 CFATTACH_DECL(mainbus, sizeof(struct device),
309     mbmatch, mbattach, NULL, NULL);
310 
311 int
312 mbmatch(pdp, cfp, auxp)
313 	struct device *pdp;
314 	struct cfdata *cfp;
315 	void *auxp;
316 {
317 	if (cfp->cf_unit > 0)
318 		return(0);
319 	/*
320 	 * We are always here
321 	 */
322 	return(1);
323 }
324 
325 /*
326  * "find" all the things that should be there.
327  */
328 void
329 mbattach(pdp, dp, auxp)
330 	struct device *pdp, *dp;
331 	void *auxp;
332 {
333 	printf ("\n");
334 
335 	config_found(dp, "intio"  , NULL);
336 	config_found(dp, "grfbus" , NULL);
337 	config_found(dp, "par"    , NULL);
338 	config_found(dp, "com"    , NULL);
339 	config_found(dp, "com"    , NULL);
340 	config_found(dp, "*"      , NULL);
341 }
342