1/*	$NetBSD$	*/
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * William Jolitz.
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. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)autoconf.c	7.1 (Berkeley) 5/9/91
35 */
36
37/*
38 * Setup the system to run on the current machine.
39 *
40 * Configure() is called at boot time and initializes the vba
41 * device tables and the memory controller monitoring.  Available
42 * devices are determined (from possibilities mentioned in ioconf.c),
43 * and the drivers are initialized.
44 */
45
46#include <sys/cdefs.h>
47__KERNEL_RCSID(0, "$NetBSD$");
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/buf.h>
52#include <sys/disk.h>
53#include <sys/disklabel.h>
54#include <sys/conf.h>
55#include <sys/reboot.h>
56#include <sys/device.h>
57#include <sys/malloc.h>
58#include <sys/queue.h>
59
60#include "pci.h"
61#if NPCI > 0
62#include <dev/pci/pcireg.h>
63#include <dev/pci/pcivar.h>
64#endif
65#include <dev/ata/atareg.h>
66#include <dev/ata/atavar.h>
67#include <dev/ata/wdvar.h>
68#include <dev/scsipi/sdvar.h>
69
70#include <machine/bootinfo.h>
71#include <machine/pte.h>
72#include <machine/intr.h>
73
74void genppc_cpu_configure(void);
75static void findroot(void);
76
77static int bus, target, lun, drive;
78static const char *name = NULL;
79
80/*
81 * Determine i/o configuration for a machine.
82 */
83
84void
85cpu_configure(void)
86{
87
88	findroot();
89
90	if (config_rootfound("mainbus", NULL) == NULL)
91		panic("configure: mainbus not configured");
92
93	genppc_cpu_configure();
94}
95
96void
97cpu_rootconf(void)
98{
99
100	aprint_normal("boot device: %s\n",
101	    booted_device ? device_xname(booted_device) : "<unknown>");
102
103	rootconf();
104}
105
106/*
107 * Attempt to find the device from which we were booted.
108 * If we can do so, and not instructed not to do so,
109 * change rootdev to correspond to the load device.
110 */
111static void
112findroot(void)
113{
114	struct btinfo_rootdevice *rdev;
115	int part;
116	char *p;
117
118	rdev = (struct btinfo_rootdevice *)lookup_bootinfo(BTINFO_ROOTDEVICE);
119	if (rdev == NULL)
120		return;
121	p = rdev->rootdevice;
122	if (strncmp(p, "/dev/disk/", 10) != 0)
123		/* unknwon device... */
124		return;
125	p += 10;
126	if (strncmp(p, "scsi/", 5) == 0) {
127		name = "sd";
128		p += 5;
129
130		bus = 0;
131		while (isdigit(*p))
132			bus = bus * 10 + (*p++) - '0';
133		if (*p++ != '/')
134			return;
135		target = 0;
136		while (isdigit(*p))
137			target = target * 10 + (*p++) - '0';
138		if (*p++ != '/')
139			return;
140		lun = 0;
141		while (isdigit(*p))
142			lun = lun * 10 + (*p++) - '0';
143	} else if (strncmp(p, "ide/", 4) == 0) {
144		name = "wd";
145		p += 4;
146
147		bus = 0;
148		while (isdigit(*p))
149			bus = bus * 10 + (*p++) - '0';
150		if (*p++ != '/')
151			return;
152		if (strncmp(p, "master/0", 8) == 0) {
153			drive = 0;
154			p += 8;
155		} else if (strncmp(p, "slave/0", 7) == 0) {
156			drive = 1;
157			p += 7;
158		} else
159			return;
160	} else if (strcmp(p, "floppy") == 0)
161		return;
162	else
163		/* unknwon disk... */
164		return;
165
166	if (*p != '_' || !isdigit(*(p + 1)))
167		return;
168	p++;
169	part = 0;
170	while (isdigit(*p))
171		part = part * 10 + (*p++) - '0';
172	if (p != '\0')
173		return;
174
175	booted_partition = part;
176}
177
178void
179device_register(device_t dev, void *aux)
180{
181	device_t bdev, cdev;
182
183#if NPCI > 0
184	if (device_is_a(dev, "genfb") &&
185	    device_is_a(device_parent(dev), "pci")) {
186		prop_dictionary_t dict = device_properties(dev);
187		struct pci_attach_args *pa = aux;
188		pcireg_t bar0;
189		uint32_t fbaddr;
190
191		bar0 = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
192		fbaddr = PCI_MAPREG_MEM_ADDR(bar0);
193
194		prop_dictionary_set_bool(dict, "is_console", 1);
195		prop_dictionary_set_uint32(dict, "width", 640);
196		prop_dictionary_set_uint32(dict, "height", 480);
197		prop_dictionary_set_uint32(dict, "depth", 8);
198		prop_dictionary_set_uint32(dict, "address", fbaddr);
199	}
200
201	if (device_is_a(dev, "siop") &&
202	    device_is_a(device_parent(dev), "pci")) {
203		prop_dictionary_t dict = device_properties(dev);
204		struct pci_attach_args *pa = aux;
205		int pbus, device;
206
207		pci_decompose_tag(pa->pa_pc, pa->pa_tag, &pbus, &device, NULL);
208		if (pbus == 0 && device == 12)
209			/* Internal SCSI uses PCI clock as SCSI clock */
210			prop_dictionary_set_bool(dict, "use_pciclock", 1);
211	}
212#endif
213
214	if (booted_device != NULL)
215		return;
216	/*
217	 * Check boot device.
218	 * It is sd/wd connected by the onboard controller to be supported.
219	 */
220	if (device_is_a(dev, "sd") && strcmp(name, "sd") == 0) {
221		struct scsipibus_attach_args *sa = aux;
222
223		bdev = device_parent(dev);
224		if (!device_is_a(bdev, "scsibus"))
225			return;
226		cdev = device_parent(bdev);
227		if (!device_is_a(cdev, "siop"))
228			return;
229
230		if (sa->sa_periph->periph_target == target &&
231		    sa->sa_periph->periph_lun == lun)
232			booted_device = dev;
233	} else if (device_is_a(dev, "wd") && strcmp(name, "wd") == 0) {
234		struct ata_device *adev = aux;
235
236		bdev = device_parent(dev);
237		if (!device_is_a(bdev, "atabus"))
238			return;
239		cdev = device_parent(bdev);
240		if (!device_is_a(cdev, "wdc"))
241			return;
242		if (!device_is_a(device_parent(cdev), "isa"))
243			return;
244
245		if (adev->adev_drv_data->drive == drive)
246			booted_device = dev;
247	}
248}
249
250