xref: /netbsd/sys/arch/sgimips/sgimips/autoconf.c (revision 6550d01e)
1 /*	$NetBSD: autoconf.c,v 1.42 2009/03/18 10:22:35 cegger 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.42 2009/03/18 10:22:35 cegger 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 struct device *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
65 cpu_configure(void)
66 {
67 	int s;
68 
69 	s = splhigh();
70 	if (config_rootfound("mainbus", NULL) == NULL)
71 		panic("no mainbus found");
72 
73 	/*
74 	 * Clear latched bus error registers which may have been
75 	 * caused by probes for non-existent devices.
76 	 */
77 	(*platform.bus_reset)();
78 
79 	/*
80 	 * Hardware interrupts will be enabled in cpu_initclocks(9)
81 	 * to avoid hardclock(9) by CPU INT5 before softclockintr is
82 	 * initialized in initclocks().
83 	 */
84 }
85 
86 /*
87  * Look at the string 'cp' and decode the boot device.  Boot names
88  * can be something like 'bootp(0)netbsd' or
89  * 'scsi(0)disk(1)rdisk(0)partition(0)netbsd' or
90  * 'dksc(0,1,0)netbsd'
91  */
92 void
93 makebootdev(const char *cp)
94 {
95 	if (booted_protocol != NULL)
96 		return;
97 
98 	booted_slot = booted_unit = booted_partition = 0;
99 
100 	if (strncmp(cp, "pci(", 4) == 0) {
101 		cp += 4;
102 
103 		while (*cp && *cp != ')')
104 		    cp++;
105 
106 		if (*cp != ')')
107 		    return;
108 
109 		cp++;
110 	}
111 
112 	if (strncmp(cp, "scsi(", 5) == 0) {
113 		cp += 5;
114 		if (*cp >= '0' && *cp <= '9')
115 			booted_slot = *cp++ - '0';
116 		if (strncmp(cp, ")disk(", 6) == 0) {
117 			cp += 6;
118 			if (*cp >= '0' && *cp <= '9')
119 				booted_unit = *cp++ - '0';
120 		}
121 		/* XXX can rdisk() ever be other than 0? */
122 		if (strncmp(cp, ")rdisk(0)partition(", 19) == 0) {
123 			cp += 19;
124 			while (*cp >= '0' && *cp <= '9')
125 				booted_partition =
126 					booted_partition * 10 + *cp++ - '0';
127 		}
128 		if (*cp != ')')
129 			return;	/* XXX ? */
130 		booted_protocol = "SCSI";
131 		return;
132 	}
133 	if (strncmp(cp, "dksc(", 5) == 0) {
134 		cp += 5;
135 		if (*cp >= '0' && *cp <= '9')
136 			booted_slot = *cp++ - '0';
137 		if (*cp == ',') {
138 			++cp;
139 			if (*cp >= '0' || *cp <= '9')
140 				booted_unit = *cp++ - '0';
141 			if (*cp == ',') {
142 				++cp;
143 				if (*cp >= '0' && *cp <= '9')
144 					booted_partition = *cp++ - '0';
145 			}
146 		}
147 		if (*cp != ')')
148 			return;		/* XXX ??? */
149 		booted_protocol = "SCSI";
150 		return;
151 	}
152 	if (strncmp(cp, "bootp(", 6) == 0) {
153 		/* XXX controller number?  Needed to
154 		   handle > 1 network controller */
155 		booted_protocol = "BOOTP";
156 		return;
157 	}
158 }
159 
160 void
161 cpu_rootconf(void)
162 {
163 	printf("boot device: %s\n",
164 		booted_device ? booted_device->dv_xname : "<unknown>");
165 
166 	setroot(booted_device, booted_partition);
167 }
168 
169 /*
170  * Try to determine the boot device and set up some device properties
171  * to handle machine dependent quirks.
172  */
173 
174 #define BUILTIN_AHC_P(pa)	\
175     (((pa)->pa_bus == 0 && (pa)->pa_device == 1 && (pa)->pa_function == 0) || \
176      ((pa)->pa_bus == 0 && (pa)->pa_device == 2 && (pa)->pa_function == 0))
177 
178 void
179 device_register(struct device *dev, void *aux)
180 {
181 	static int found, initted, scsiboot, netboot;
182 	struct device *parent = device_parent(dev);
183 
184 	if (mach_type == MACH_SGI_IP32 &&
185 	    parent != NULL && device_is_a(parent, "pci")) {
186 		struct pci_attach_args *pa = aux;
187 
188 		if (BUILTIN_AHC_P(pa)) {
189 			if (prop_dictionary_set_bool(device_properties(dev),
190 			    "aic7xxx-use-target-defaults", true) == false) {
191 				printf("WARNING: unable to set "
192 				    "aic7xxx-use-target-defaults property "
193 				    "for %s\n", dev->dv_xname);
194 			}
195 
196 			if (prop_dictionary_set_bool(device_properties(dev),
197 			    "aic7xxx-override-ultra", true) == false) {
198 				printf("WARNING: unable to set "
199 				    "aic7xxx-override-ultra property for %s\n",
200 				    dev->dv_xname);
201 			}
202 		}
203 	}
204 
205 	/*
206 	 * The Set Engineering GIO Fast Ethernet controller has restrictions
207 	 * on DMA boundaries.
208 	 */
209 	if (device_is_a(dev, "tl")) {
210 		struct device *grandparent;
211 		prop_number_t gfe_boundary;
212 
213 		grandparent = device_parent(parent);
214 		if (grandparent != NULL && device_is_a(grandparent, "giopci")) {
215 			gfe_boundary = prop_number_create_integer(PAGE_SIZE);
216 			KASSERT(gfe_boundary != NULL);
217 
218 			if (prop_dictionary_set(device_properties(dev),
219 			    "tl-dma-page-boundary", gfe_boundary) == false) {
220 				printf("WARNING: unable to set "
221 				    "tl-dma-page-boundary property "
222 				    "for %s\n", dev->dv_xname);
223 			}
224 			prop_object_release(gfe_boundary);
225 			return;
226 		}
227 	}
228 
229 	if (found)
230 		return;
231 
232 	if (!initted && booted_protocol) {
233 		scsiboot = strcmp(booted_protocol, "SCSI") == 0;
234 		netboot = (strcmp(booted_protocol, "BOOTP") == 0);
235 		initted = 1;
236 	}
237 
238 	/*
239 	 * Handle SCSI boot device definitions
240 	 * wdsc -- IP12/22/24
241 	 * ahc -- IP32
242 	 */
243 	if ( (scsiboot && device_is_a(dev, "wdsc")) ||
244 	     (scsiboot && device_is_a(dev, "ahc")) ) {
245 		/* XXX device_unit() abuse */
246 		if (device_unit(dev) == booted_slot)
247 			booted_controller = dev;
248 		return;
249 	}
250 
251 	/*
252 	 * If we found the boot controller, if check disk/tape/cdrom device
253 	 * on that controller matches.
254 	 */
255 	if (booted_controller &&
256 	    (device_is_a(dev, "sd") ||
257 	     device_is_a(dev, "st") ||
258 	     device_is_a(dev, "cd"))) {
259 		struct scsipibus_attach_args *sa = aux;
260 
261 		if (device_parent(parent) != booted_controller)
262 			return;
263 		if (booted_unit != sa->sa_periph->periph_target)
264 			return;
265 		booted_device = dev;
266 		found = 1;
267 		return;
268 	}
269 
270 	/*
271 	 * Check if netboot device.
272 	 */
273 	if (netboot &&
274 	    (device_is_a(dev, "sq") ||
275 	     device_is_a(dev, "mec"))) {
276 		/* XXX Check unit number? (Which we don't parse yet) */
277 		booted_device = dev;
278 		found = 1;
279 		return;
280 	}
281 }
282