xref: /netbsd/sys/arch/x68k/x68k/autoconf.c (revision bf9ec67e)
1 /*	$NetBSD: autoconf.c,v 1.27 2002/05/16 02:50:55 thorpej 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 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/reboot.h>
38 #include <sys/conf.h>
39 #include <sys/device.h>
40 #include <sys/disk.h>
41 #include <sys/disklabel.h>
42 #include <sys/malloc.h>
43 #include <machine/cpu.h>
44 #include <x68k/x68k/iodevice.h>
45 #include <machine/bootinfo.h>
46 
47 #include <dev/scsipi/scsi_all.h>
48 #include <dev/scsipi/scsipi_all.h>
49 #include <dev/scsipi/scsiconf.h>
50 
51 void configure __P((void));
52 static void findroot __P((void));
53 void mbattach __P((struct device *, struct device *, void *));
54 int mbmatch __P((struct device *, struct cfdata*, void*));
55 int x68k_config_found __P((struct cfdata *, struct device *,
56 			   void *, cfprint_t));
57 
58 static int simple_devprint __P((void *, const char *));
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 /*ARGSUSED*/
96 static int
97 simple_devprint(auxp, pnp)
98 	void *auxp;
99 	const char *pnp;
100 {
101 	return(QUIET);
102 }
103 
104 /*
105  * use config_search to find appropriate device, then call that device
106  * directly with NULL device variable storage.  A device can then
107  * always tell the difference between the real and console init
108  * by checking for NULL.
109  */
110 int
111 x68k_config_found(pcfp, pdp, auxp, pfn)
112 	struct cfdata *pcfp;
113 	struct device *pdp;
114 	void *auxp;
115 	cfprint_t pfn;
116 {
117 	struct device temp;
118 	struct cfdata *cf;
119 
120 	if (x68k_realconfig)
121 		return(config_found(pdp, auxp, pfn) != NULL);
122 
123 	if (pdp == NULL)
124 		pdp = &temp;
125 
126 	pdp->dv_cfdata = pcfp;
127 	if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
128 		cf->cf_attach->ca_attach(pdp, NULL, auxp);
129 		pdp->dv_cfdata = NULL;
130 		return(1);
131 	}
132 	pdp->dv_cfdata = NULL;
133 	return(0);
134 }
135 
136 /*
137  * this function needs to get enough configured to do a console
138  * basically this means start attaching the grfxx's that support
139  * the console. Kinda hacky but it works.
140  */
141 void
142 config_console()
143 {
144 	struct cfdata *cf;
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 i, majdev, unit, part;
163 	char buf[32];
164 
165 	if (booted_device)
166 		return;
167 
168 	if (boothowto & RB_ASKNAME)
169 		return;		/* Don't bother looking */
170 
171 	if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
172 		return;
173 
174 	majdev = B_TYPE(bootdev);
175 	if (X68K_BOOT_DEV_IS_SCSI(majdev)) {
176 		/*
177 		 * SCSI device
178 		 */
179 		if ((booted_device = scsi_find(bootdev)) != NULL)
180 			booted_partition = B_X68K_SCSI_PART(bootdev);
181 		return;
182 	}
183 	for (i = 0; dev_name2blk[i].d_name != NULL; i++)
184 		if (majdev == dev_name2blk[i].d_maj)
185 			break;
186 	if (dev_name2blk[i].d_name == NULL)
187 		return;
188 
189 	part = B_PARTITION(bootdev);
190 	unit = B_UNIT(bootdev);
191 
192 	sprintf(buf, "%s%d", dev_name2blk[i].d_name, unit);
193 
194 	if ((booted_device = find_dev_byname(buf)) != NULL)
195 		booted_partition = part;
196 }
197 
198 static const char *const name_netif[] = { X68K_BOOT_NETIF_STRINGS };
199 
200 void
201 device_register(dev, aux)
202 	struct device *dev;
203 	void *aux;
204 {
205 	int majdev;
206 	char tname[16];
207 
208 	/*
209 	 * Handle network interfaces here, the attachment information is
210 	 * not available driver independantly later.
211 	 * For disks, there is nothing useful available at attach time.
212 	 */
213 	if (dev->dv_class == DV_IFNET) {
214 		majdev = B_TYPE(bootdev);
215 		if (X68K_BOOT_DEV_IS_NETIF(majdev)) {
216 			sprintf(tname, "%s%d",
217 				name_netif[255 - majdev], B_UNIT(bootdev));
218 			if (!strcmp(tname, dev->dv_xname))
219 				goto found;
220 		}
221 	}
222 	return;
223 
224 found:
225 	if (booted_device) {
226 		/* XXX should be a "panic()" */
227 		printf("warning: double match for boot device (%s, %s)\n",
228 		       booted_device->dv_xname, dev->dv_xname);
229 		return;
230 	}
231 	booted_device = dev;
232 }
233 
234 static const char *const name_scsiif[] = { X68K_BOOT_SCSIIF_STRINGS };
235 
236 static struct device *
237 scsi_find(bdev)
238 	dev_t bdev;	/* encoded boot device */
239 {
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 -- update boot loader\n");
256 		scsibus = find_dev_byname("scsibus0");
257 #else
258 		/* can't determine interface type */
259 		return NULL;
260 #endif
261 	} else {
262 		/*
263 		 * search for the scsibus whose parent is
264 		 * the specified SCSI interface
265 		 */
266 		sprintf(tname, "%s%d",
267 			name_scsiif[ifid], B_X68K_SCSI_IF_UN(bdev));
268 
269 		for (scsibus = TAILQ_FIRST(&alldevs); scsibus;
270 					scsibus = TAILQ_NEXT(scsibus, dv_list))
271 			if (scsibus->dv_parent
272 			    && !strcmp(tname, scsibus->dv_parent->dv_xname))
273 				break;
274 	}
275 	if (!scsibus)
276 		return NULL;
277 	sbsc = (struct scsibus_softc *) scsibus;
278 	periph = scsipi_lookup_periph(sbsc->sc_channel,
279 	    B_X68K_SCSI_ID(bdev), B_X68K_SCSI_LUN(bdev));
280 
281 	return periph ? periph->periph_dev : NULL;
282 }
283 
284 /*
285  * Given a device name, find its struct device
286  * XXX - Move this to some common file?
287  */
288 static struct device *
289 find_dev_byname(name)
290 	const char *name;
291 {
292 	struct device *dv;
293 
294 	for (dv = TAILQ_FIRST(&alldevs); dv; dv = TAILQ_NEXT(dv, dv_list))
295 		if (!strcmp(dv->dv_xname, name))
296 			break;
297 
298 	return dv;
299 }
300 
301 /*
302  * mainbus driver
303  */
304 struct cfattach mainbus_ca = {
305 	sizeof(struct device), mbmatch, mbattach
306 };
307 
308 int
309 mbmatch(pdp, cfp, auxp)
310 	struct device *pdp;
311 	struct cfdata *cfp;
312 	void *auxp;
313 {
314 	if (cfp->cf_unit > 0)
315 		return(0);
316 	/*
317 	 * We are always here
318 	 */
319 	return(1);
320 }
321 
322 /*
323  * "find" all the things that should be there.
324  */
325 void
326 mbattach(pdp, dp, auxp)
327 	struct device *pdp, *dp;
328 	void *auxp;
329 {
330 	printf ("\n");
331 	config_found(dp, "intio"  , simple_devprint);
332 	config_found(dp, "grfbus" , simple_devprint);
333 	config_found(dp, "par"    , simple_devprint);
334 	config_found(dp, "com"    , simple_devprint);
335 	config_found(dp, "com"    , simple_devprint);
336 /*	config_found(dp, "adpcm"  , simple_devprint);	*/
337 	config_found(dp, "*"      , simple_devprint);
338 }
339