xref: /netbsd-src/sys/arch/sgimips/sgimips/autoconf.c (revision d07fd9689bda45b4eb44341240b90fd10b48f7f3)
1 /*	$NetBSD: autoconf.c,v 1.45 2013/12/16 15:45:29 mrg Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Soren S. Jorvang
5  * All rights reserved.
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 for the
18  *          NetBSD Project.  See http://www.NetBSD.org/ for
19  *          information about NetBSD.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.45 2013/12/16 15:45:29 mrg Exp $");
37 
38 #include "opt_ddb.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/buf.h>
43 #include <sys/conf.h>
44 #include <sys/device.h>
45 
46 #include <machine/cpu.h>
47 #include <machine/sysconf.h>
48 #include <machine/machtype.h>
49 #include <machine/autoconf.h>
50 #include <machine/vmparam.h>	/* for PAGE_SIZE */
51 
52 #include <dev/pci/pcivar.h>
53 
54 #include <dev/scsipi/scsi_all.h>
55 #include <dev/scsipi/scsipi_all.h>
56 #include <dev/scsipi/scsiconf.h>
57 
58 static device_t booted_controller = NULL;
59 static int	booted_slot, booted_unit;
60 static const char	*booted_protocol = NULL;
61 
62 extern struct platform platform;
63 
64 void
cpu_configure(void)65 cpu_configure(void)
66 {
67 
68 	(void)splhigh();
69 	if (config_rootfound("mainbus", NULL) == NULL)
70 		panic("no mainbus found");
71 
72 	/*
73 	 * Clear latched bus error registers which may have been
74 	 * caused by probes for non-existent devices.
75 	 */
76 	(*platform.bus_reset)();
77 
78 	/*
79 	 * Hardware interrupts will be enabled in cpu_initclocks(9)
80 	 * to avoid hardclock(9) by CPU INT5 before softclockintr is
81 	 * initialized in initclocks().
82 	 */
83 }
84 
85 /*
86  * Look at the string 'cp' and decode the boot device.  Boot names
87  * can be something like 'bootp(0)netbsd' or
88  * 'scsi(0)disk(1)rdisk(0)partition(0)netbsd' or
89  * 'dksc(0,1,0)netbsd'
90  */
91 void
makebootdev(const char * cp)92 makebootdev(const char *cp)
93 {
94 	if (booted_protocol != NULL)
95 		return;
96 
97 	booted_slot = booted_unit = booted_partition = 0;
98 
99 	if (strncmp(cp, "pci(", 4) == 0) {
100 		cp += 4;
101 
102 		while (*cp && *cp != ')')
103 		    cp++;
104 
105 		if (*cp != ')')
106 		    return;
107 
108 		cp++;
109 	}
110 
111 	if (strncmp(cp, "scsi(", 5) == 0) {
112 		cp += 5;
113 		if (*cp >= '0' && *cp <= '9')
114 			booted_slot = *cp++ - '0';
115 		if (strncmp(cp, ")disk(", 6) == 0) {
116 			cp += 6;
117 			if (*cp >= '0' && *cp <= '9')
118 				booted_unit = *cp++ - '0';
119 		}
120 		/* XXX can rdisk() ever be other than 0? */
121 		if (strncmp(cp, ")rdisk(0)partition(", 19) == 0) {
122 			cp += 19;
123 			while (*cp >= '0' && *cp <= '9')
124 				booted_partition =
125 					booted_partition * 10 + *cp++ - '0';
126 		}
127 		if (*cp != ')')
128 			return;	/* XXX ? */
129 		booted_protocol = "SCSI";
130 		return;
131 	}
132 	if (strncmp(cp, "dksc(", 5) == 0) {
133 		cp += 5;
134 		if (*cp >= '0' && *cp <= '9')
135 			booted_slot = *cp++ - '0';
136 		if (*cp == ',') {
137 			++cp;
138 			if (*cp >= '0' || *cp <= '9')
139 				booted_unit = *cp++ - '0';
140 			if (*cp == ',') {
141 				++cp;
142 				if (*cp >= '0' && *cp <= '9')
143 					booted_partition = *cp++ - '0';
144 			}
145 		}
146 		if (*cp != ')')
147 			return;		/* XXX ??? */
148 		booted_protocol = "SCSI";
149 		return;
150 	}
151 	if (strncmp(cp, "bootp(", 6) == 0) {
152 		/* XXX controller number?  Needed to
153 		   handle > 1 network controller */
154 		booted_protocol = "BOOTP";
155 		return;
156 	}
157 }
158 
159 void
cpu_rootconf(void)160 cpu_rootconf(void)
161 {
162 	printf("boot device: %s\n",
163 		booted_device ? device_xname(booted_device) : "<unknown>");
164 
165 	rootconf();
166 }
167 
168 /*
169  * Try to determine the boot device and set up some device properties
170  * to handle machine dependent quirks.
171  */
172 
173 #define BUILTIN_AHC_P(pa)	\
174     (((pa)->pa_bus == 0 && (pa)->pa_device == 1 && (pa)->pa_function == 0) || \
175      ((pa)->pa_bus == 0 && (pa)->pa_device == 2 && (pa)->pa_function == 0))
176 
177 void
device_register(device_t dev,void * aux)178 device_register(device_t dev, void *aux)
179 {
180 	static int found, initted, scsiboot, netboot;
181 	device_t parent = device_parent(dev);
182 
183 	if (mach_type == MACH_SGI_IP32 &&
184 	    parent != NULL && device_is_a(parent, "pci")) {
185 		struct pci_attach_args *pa = aux;
186 
187 		if (BUILTIN_AHC_P(pa)) {
188 			if (prop_dictionary_set_bool(device_properties(dev),
189 			    "aic7xxx-use-target-defaults", true) == false) {
190 				printf("WARNING: unable to set "
191 				    "aic7xxx-use-target-defaults property "
192 				    "for %s\n", device_xname(dev));
193 			}
194 
195 			if (prop_dictionary_set_bool(device_properties(dev),
196 			    "aic7xxx-override-ultra", true) == false) {
197 				printf("WARNING: unable to set "
198 				    "aic7xxx-override-ultra property for %s\n",
199 				    device_xname(dev));
200 			}
201 		}
202 	}
203 
204 	/*
205 	 * The Set Engineering GIO Fast Ethernet controller has restrictions
206 	 * on DMA boundaries.
207 	 */
208 	if (device_is_a(dev, "tl")) {
209 		device_t grandparent;
210 		prop_number_t gfe_boundary;
211 
212 		grandparent = device_parent(parent);
213 		if (grandparent != NULL && device_is_a(grandparent, "giopci")) {
214 			gfe_boundary = prop_number_create_integer(PAGE_SIZE);
215 			KASSERT(gfe_boundary != NULL);
216 
217 			if (prop_dictionary_set(device_properties(dev),
218 			    "tl-dma-page-boundary", gfe_boundary) == false) {
219 				printf("WARNING: unable to set "
220 				    "tl-dma-page-boundary property "
221 				    "for %s\n", device_xname(dev));
222 			}
223 			prop_object_release(gfe_boundary);
224 			return;
225 		}
226 	}
227 
228 	if (found)
229 		return;
230 
231 	if (!initted && booted_protocol) {
232 		scsiboot = strcmp(booted_protocol, "SCSI") == 0;
233 		netboot = (strcmp(booted_protocol, "BOOTP") == 0);
234 		initted = 1;
235 	}
236 
237 	/*
238 	 * Handle SCSI boot device definitions
239 	 * wdsc -- IP12/22/24
240 	 * ahc -- IP32
241 	 */
242 	if ( (scsiboot && device_is_a(dev, "wdsc")) ||
243 	     (scsiboot && device_is_a(dev, "ahc")) ) {
244 		/* XXX device_unit() abuse */
245 		if (device_unit(dev) == booted_slot)
246 			booted_controller = dev;
247 		return;
248 	}
249 
250 	/*
251 	 * If we found the boot controller, if check disk/tape/cdrom device
252 	 * on that controller matches.
253 	 */
254 	if (booted_controller &&
255 	    (device_is_a(dev, "sd") ||
256 	     device_is_a(dev, "st") ||
257 	     device_is_a(dev, "cd"))) {
258 		struct scsipibus_attach_args *sa = aux;
259 
260 		if (device_parent(parent) != booted_controller)
261 			return;
262 		if (booted_unit != sa->sa_periph->periph_target)
263 			return;
264 		booted_device = dev;
265 		found = 1;
266 		return;
267 	}
268 
269 	/*
270 	 * Check if netboot device.
271 	 */
272 	if (netboot &&
273 	    (device_is_a(dev, "sq") ||
274 	     device_is_a(dev, "mec"))) {
275 		/* XXX Check unit number? (Which we don't parse yet) */
276 		booted_device = dev;
277 		found = 1;
278 		return;
279 	}
280 }
281