autoconf.c revision 1.1
1/*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
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. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: Utah $Hdr: autoconf.c 1.31 91/01/21$
39 *
40 *	@(#)autoconf.c	7.5 (Berkeley) 5/7/91
41 */
42
43/*
44 * Setup the system to run on the current machine.
45 *
46 * Configure() is called at boot time.  Available
47 * devices are determined (from possibilities mentioned in ioconf.c),
48 * and the drivers are initialized.
49 */
50
51#include "sys/param.h"
52#include "sys/systm.h"
53#include "sys/buf.h"
54#include "sys/dkstat.h"
55#include "sys/conf.h"
56#include "sys/dmap.h"
57#include "sys/reboot.h"
58
59#include "machine/vmparam.h"
60#include "machine/cpu.h"
61#include "pte.h"
62#include "../dev/device.h"
63
64#include <libraries/configregs.h>
65#include <libraries/configvars.h>
66
67/*
68 * The following several variables are related to
69 * the configuration process, and are used in initializing
70 * the machine.
71 */
72int	cold;		    /* if 1, still working on cold-start */
73int	dkn;		    /* number of iostat dk numbers assigned so far */
74int	cpuspeed = MHZ_8;   /* relative cpu speed */
75struct	amiga_hw sc_table[MAXCTLRS];
76
77#ifdef DEBUG
78int	acdebug = 0;
79#endif
80
81/*
82 * Determine mass storage and memory configuration for a machine.
83 */
84configure()
85{
86	register struct amiga_hw *hw;
87	int found;
88
89	/*
90	 * XXX: these should be consolidated into some kind of table
91	 */
92	dmainit();
93
94	/*
95	 * Look over each hardware device actually found and attempt
96	 * to match it with an ioconf.c table entry.
97	 */
98	for (hw = sc_table; hw->hw_type; hw++) {
99		if (HW_ISCTLR(hw))
100			found = find_controller(hw);
101		else
102			found = find_device(hw);
103#ifdef DEBUG
104		if (!found && acdebug) {
105			printf("unconfigured device %d/%d\n",
106			       hw->hw_manufacturer, hw->hw_product);
107		}
108#endif
109	}
110
111#if 0
112#include "cd.h"
113#if NCD > 0
114	/*
115	 * Now deal with concatenated disks
116	 */
117	find_cdevices();
118#endif
119#endif
120
121#if GENERIC
122	if ((boothowto & RB_ASKNAME) == 0)
123		setroot();
124	setconf();
125#else
126	setroot();
127#endif
128	swapconf();
129	cold = 0;
130}
131
132#define dr_type(d, s)	\
133	(strcmp((d)->d_name, (s)) == 0)
134
135#define same_hw_ctlr(hw, ac) \
136	(HW_ISFLOPPY(hw) && dr_type((ac)->amiga_driver, "floppy") || \
137	 HW_ISSCSI(hw) && dr_type((ac)->amiga_driver, "scsi"))
138
139find_controller(hw)
140	register struct amiga_hw *hw;
141{
142	register struct amiga_ctlr *ac;
143	struct amiga_ctlr *match_c;
144	caddr_t oaddr;
145	int sc;
146
147#ifdef DEBUG
148	if (acdebug)
149		printf("find_controller: hw: [%d/%d] (%x), type %x...",
150		       hw->hw_manufacturer, hw->hw_product,
151		       hw->hw_kva, hw->hw_type);
152#endif
153	sc = (hw->hw_manufacturer << 16) | hw->hw_product;
154	match_c = NULL;
155	for (ac = amiga_cinit; ac->amiga_driver; ac++) {
156		if (ac->amiga_alive)
157			continue;
158		/*
159		 * Make sure we are looking at the right
160		 * controller type.
161		 */
162		if (!same_hw_ctlr(hw, ac))
163			continue;
164		/*
165		 * Exact match; all done
166		 */
167		if ((int)ac->amiga_addr == sc) {
168			match_c = ac;
169			break;
170		}
171		/*
172		 * Wildcard; possible match so remember first instance
173		 * but continue looking for exact match.
174		 */
175		if (ac->amiga_addr == NULL && match_c == NULL)
176			match_c = ac;
177	}
178#ifdef DEBUG
179	if (acdebug) {
180		if (match_c)
181			printf("found %s%d\n",
182			       match_c->amiga_driver->d_name,
183			       match_c->amiga_unit);
184		else
185			printf("not found\n");
186	}
187#endif
188	/*
189	 * Didn't find an ioconf entry for this piece of hardware,
190	 * just ignore it.
191	 */
192	if (match_c == NULL)
193		return(0);
194	/*
195	 * Found a match, attempt to initialize and configure all attached
196	 * slaves.  Note, we can still fail if HW won't initialize.
197	 */
198	ac = match_c;
199	oaddr = ac->amiga_addr;
200	ac->amiga_addr = hw->hw_kva;
201	if ((*ac->amiga_driver->d_init)(ac)) {
202		ac->amiga_alive = 1;
203		printf ("%s%d", ac->amiga_driver->d_name, ac->amiga_unit);
204		printf (" [%d/%d]", hw->hw_manufacturer, hw->hw_product);
205		if (ac->amiga_flags)
206			printf(", flags 0x%x", ac->amiga_flags);
207		printf("\n");
208		find_slaves(ac);
209	} else
210		ac->amiga_addr = oaddr;
211	return(1);
212}
213
214find_device(hw)
215	register struct amiga_hw *hw;
216{
217	register struct amiga_device *ad;
218	struct amiga_device *match_d;
219	caddr_t oaddr;
220	int sc;
221
222#ifdef DEBUG
223	if (acdebug)
224		printf("find_device: hw: [%d/%d] (%x), type %x...",
225		       hw->hw_manufacturer, hw->hw_product,
226		       hw->hw_kva, hw->hw_type);
227#endif
228	match_d = NULL;
229	for (ad = amiga_dinit; ad->amiga_driver; ad++) {
230		if (ad->amiga_alive)
231			continue;
232		/* Must not be a slave */
233		if (ad->amiga_cdriver)
234			continue;
235
236		sc = (int) ad->amiga_addr;
237		/*
238		 * Exact match; all done.
239		 */
240		if (sc > 0 && sc == ((hw->hw_manufacturer << 16) | hw->hw_product)) {
241			match_d = ad;
242			break;
243		}
244		/*
245		 * Wildcard; possible match so remember first instance
246		 * but continue looking for exact match.
247		 */
248		if (sc == 0 && same_hw_device(hw, ad) && match_d == NULL)
249			match_d = ad;
250	}
251#ifdef DEBUG
252	if (acdebug) {
253		if (match_d)
254			printf("found %s%d\n",
255			       match_d->amiga_driver->d_name,
256			       match_d->amiga_unit);
257		else
258			printf("not found\n");
259	}
260#endif
261	/*
262	 * Didn't find an ioconf entry for this piece
263	 * of hardware, just ignore it.
264	 */
265	if (match_d == NULL)
266		return(0);
267	/*
268	 * Found a match, attempt to initialize.
269	 * Note, we can still fail if HW won't initialize.
270	 */
271	ad = match_d;
272	oaddr = ad->amiga_addr;
273	ad->amiga_addr = hw->hw_kva;
274	if ((*ad->amiga_driver->d_init)(ad)) {
275		ad->amiga_alive = 1;
276		printf("%s%d", ad->amiga_driver->d_name, ad->amiga_unit);
277		printf (" [%d/%d]", hw->hw_manufacturer, hw->hw_product);
278		if (ad->amiga_flags)
279			printf(", flags 0x%x", ad->amiga_flags);
280		printf("\n");
281	} else
282		ad->amiga_addr = oaddr;
283	return(1);
284}
285
286find_slaves(ac)
287	struct amiga_ctlr *ac;
288{
289	if (dr_type(ac->amiga_driver, "floppy"))
290		find_busslaves(ac, 4);
291	else if (dr_type(ac->amiga_driver, "scsi"))
292		find_busslaves(ac, 7);
293}
294
295/*
296 */
297find_busslaves(ac, maxslaves)
298	register struct amiga_ctlr *ac;
299	int maxslaves;
300{
301	register int s;
302	register struct amiga_device *ad;
303	struct amiga_device *match_s;
304	int new_s, new_c, old_s, old_c;
305	int rescan;
306
307#ifdef DEBUG
308	if (acdebug)
309		printf("find_busslaves: for %s%d\n",
310		       ac->amiga_driver->d_name, ac->amiga_unit);
311#endif
312	for (s = 0; s < maxslaves; s++) {
313		rescan = 1;
314		match_s = NULL;
315		for (ad = amiga_dinit; ad->amiga_driver; ad++) {
316			/*
317			 * Rule out the easy ones:
318			 * 1. slave already assigned or not a slave
319			 * 2. not of the proper type
320			 * 3. controller specified but not this one
321			 * 4. slave specified but not this one
322			 */
323			if (ad->amiga_alive || ad->amiga_cdriver == NULL)
324				continue;
325			if (!dr_type(ac->amiga_driver, ad->amiga_cdriver->d_name))
326				continue;
327			if (ad->amiga_ctlr >= 0 && ad->amiga_ctlr != ac->amiga_unit)
328				continue;
329			if (ad->amiga_slave >= 0 && ad->amiga_slave != s)
330				continue;
331			/*
332			 * Case 0: first possible match.
333			 * Remember it and keep looking for better.
334			 */
335			if (match_s == NULL) {
336				match_s = ad;
337				new_c = ac->amiga_unit;
338				new_s = s;
339				continue;
340			}
341			/*
342			 * Case 1: exact match.
343			 * All done.  Note that we do not attempt any other
344			 * matches if this one fails.  This allows us to
345			 * "reserve" locations for dynamic addition of
346			 * disk/tape drives by fully qualifing the location.
347			 */
348			if (ad->amiga_slave == s && ad->amiga_ctlr == ac->amiga_unit) {
349				match_s = ad;
350				rescan = 0;
351				break;
352			}
353			/*
354			 * Case 2: right controller, wildcarded slave.
355			 * Remember first and keep looking for an exact match.
356			 */
357			if (ad->amiga_ctlr == ac->amiga_unit &&
358			    match_s->amiga_ctlr < 0) {
359				match_s = ad;
360				new_s = s;
361				continue;
362			}
363			/*
364			 * Case 3: right slave, wildcarded controller.
365			 * Remember and keep looking for a better match.
366			 */
367			if (ad->amiga_slave == s &&
368			    match_s->amiga_ctlr < 0 && match_s->amiga_slave < 0) {
369				match_s = ad;
370				new_c = ac->amiga_unit;
371				continue;
372			}
373			/*
374			 * OW: we had a totally wildcarded spec.
375			 * If we got this far, we have found a possible
376			 * match already (match_s != NULL) so there is no
377			 * reason to remember this one.
378			 */
379			continue;
380		}
381		/*
382		 * Found a match.  We need to set amiga_ctlr/amiga_slave properly
383		 * for the init routines but we also need to remember all
384		 * the old values in case this doesn't pan out.
385		 */
386		if (match_s) {
387			ad = match_s;
388			old_c = ad->amiga_ctlr;
389			old_s = ad->amiga_slave;
390			if (ad->amiga_ctlr < 0)
391				ad->amiga_ctlr = new_c;
392			if (ad->amiga_slave < 0)
393				ad->amiga_slave = new_s;
394#ifdef DEBUG
395			if (acdebug)
396				printf("looking for %s%d at slave %d...",
397				       ad->amiga_driver->d_name,
398				       ad->amiga_unit, ad->amiga_slave);
399#endif
400
401			if ((*ad->amiga_driver->d_init)(ad)) {
402#ifdef DEBUG
403				if (acdebug)
404					printf("found\n");
405#endif
406				printf("%s%d at %s%d, slave %d",
407				       ad->amiga_driver->d_name, ad->amiga_unit,
408				       ac->amiga_driver->d_name, ad->amiga_ctlr,
409				       ad->amiga_slave);
410				if (ad->amiga_flags)
411					printf(" flags 0x%x", ad->amiga_flags);
412				printf("\n");
413				ad->amiga_alive = 1;
414				if (ad->amiga_dk && dkn < DK_NDRIVE)
415					ad->amiga_dk = dkn++;
416				else
417					ad->amiga_dk = -1;
418				rescan = 1;
419			} else {
420#ifdef DEBUG
421				if (acdebug)
422					printf("not found\n");
423#endif
424				ad->amiga_ctlr = old_c;
425				ad->amiga_slave = old_s;
426			}
427			/*
428			 * XXX: This should be handled better.
429			 * Re-scan a slave.  There are two reasons to do this.
430			 * 1. It is possible to have both a tape and disk
431			 *    (e.g. 7946) or two disks (e.g. 9122) at the
432			 *    same slave address.  Here we need to rescan
433			 *    looking only at entries with a different
434			 *    physical unit number (amiga_flags).
435			 * 2. It is possible that an init failed because the
436			 *    slave was there but of the wrong type.  In this
437			 *    case it may still be possible to match the slave
438			 *    to another ioconf entry of a different type.
439			 *    Here we need to rescan looking only at entries
440			 *    of different types.
441			 * In both cases we avoid looking at undesirable
442			 * ioconf entries of the same type by setting their
443			 * alive fields to -1.
444			 */
445			if (rescan) {
446				for (ad = amiga_dinit; ad->amiga_driver; ad++) {
447					if (ad->amiga_alive)
448						continue;
449					if (match_s->amiga_alive == 1) {	/* 1 */
450						if (ad->amiga_flags == match_s->amiga_flags)
451							ad->amiga_alive = -1;
452					} else {			/* 2 */
453						if (ad->amiga_driver == match_s->amiga_driver)
454							ad->amiga_alive = -1;
455					}
456				}
457				s--;
458				continue;
459			}
460		}
461		/*
462		 * Reset bogon alive fields prior to attempting next slave
463		 */
464		for (ad = amiga_dinit; ad->amiga_driver; ad++)
465			if (ad->amiga_alive == -1)
466				ad->amiga_alive = 0;
467	}
468}
469
470same_hw_device(hw, ad)
471	struct amiga_hw *hw;
472	struct amiga_device *ad;
473{
474	int found = 0;
475
476	switch (hw->hw_type & ~B_MASK) {
477	case C_FLOPPY:
478		found = dr_type(ad->amiga_driver, "floppy");
479		break;
480	case C_SCSI:
481		found = dr_type(ad->amiga_driver, "scsi");
482		break;
483	case D_BITMAP:
484		found = dr_type(ad->amiga_driver, "grf");
485		break;
486	case D_LAN:
487		found = dr_type(ad->amiga_driver, "le");
488		break;
489	case D_COMMSER:
490		found = dr_type(ad->amiga_driver, "ser");
491		break;
492	default:
493		break;
494	}
495	return(found);
496}
497
498char notmappedmsg[] = "WARNING: no space to map IO card, ignored\n";
499
500/*
501 * Scan the IO space looking for devices.
502 */
503find_devs()
504{
505  short sc;
506  u_char *id_reg;
507  register caddr_t addr;
508  register struct amiga_hw *hw;
509  int didmap, sctop;
510  extern int num_ConfigDev;
511  extern struct ConfigDev *ConfigDev;
512  struct ConfigDev *cd;
513
514#if 0
515  /*
516   * Initialize IO resource map for iomap().
517   */
518  rminit(extiomap, (long)EIOMAPSIZE, (long)1, "extio", EIOMAPSIZE/16);
519#endif
520  hw = sc_table;
521
522  /* first enter builtin devices */
523
524  /* this is only for the A3000, but... */
525  hw->hw_pa	      = 0xdd0000;
526  hw->hw_size	      = NBPG;
527  hw->hw_kva	      = 0;			/* filled out in scsiinit */
528  hw->hw_manufacturer = MANUF_BUILTIN;
529  hw->hw_product      = PROD_BUILTIN_SCSI;
530  hw->hw_type	      = B_BUILTIN | C_SCSI;
531  hw++;
532
533  hw->hw_pa	      = 0xdc0000;
534  hw->hw_size	      = NBPG;
535  hw->hw_kva	      = 0;			/* should be mapped here! */
536  hw->hw_manufacturer = MANUF_BUILTIN;
537  hw->hw_product      = PROD_BUILTIN_CLOCK;
538  hw->hw_type	      = B_BUILTIN | D_CLOCK;
539  hw++;
540
541  hw->hw_pa	      = 0;
542  hw->hw_size	      = 0;
543  hw->hw_kva	      = 0;			/* already mapped, uses CUSTOMbase */
544  hw->hw_manufacturer = MANUF_BUILTIN;
545  hw->hw_product      = PROD_BUILTIN_FLOPPY;
546  hw->hw_type	      = B_BUILTIN | C_FLOPPY;
547  hw++;
548
549  hw->hw_pa	      = 0;
550  hw->hw_size	      = 0;
551  hw->hw_kva	      = 0;			/* already mapped, uses CUSTOMbase */
552  hw->hw_manufacturer = MANUF_BUILTIN;
553  hw->hw_product      = PROD_BUILTIN_RS232;
554  hw->hw_type	      = B_BUILTIN | D_COMMSER;
555  hw++;
556
557  hw->hw_pa	      = 0;
558  hw->hw_size	      = 0;
559  hw->hw_kva	      = 0;			/* already mapped, uses CUSTOMbase */
560  hw->hw_manufacturer = MANUF_BUILTIN;
561  hw->hw_product      = PROD_BUILTIN_KEYBOARD;
562  hw->hw_type	      = B_BUILTIN | D_KEYBOARD;
563  hw++;
564
565  hw->hw_pa	      = 0;
566  hw->hw_size	      = 0;
567  hw->hw_kva	      = 0;			/* already mapped, uses CUSTOMbase */
568  hw->hw_manufacturer = MANUF_BUILTIN;
569  hw->hw_product      = PROD_BUILTIN_PPORT;
570  hw->hw_type	      = B_BUILTIN | D_PPORT;
571  hw++;
572
573  hw->hw_pa	      = 0;
574  hw->hw_size	      = 0;
575  hw->hw_kva	      = 0;			/* already mapped, uses CUSTOMbase */
576  hw->hw_manufacturer = MANUF_BUILTIN;
577  hw->hw_product      = PROD_BUILTIN_DISPLAY;
578  hw->hw_type	      = B_BUILTIN | D_BITMAP;
579  hw++;
580
581  /* and afterwards add Zorro II/III devices passed by the loader */
582
583  for (sc = 0, cd = ConfigDev; sc < num_ConfigDev; sc++, cd++)
584    {
585      hw->hw_pa		  = cd->cd_BoardAddr;
586      hw->hw_size	  = cd->cd_BoardSize;
587      hw->hw_kva	  = 0;			/* XXX */
588      hw->hw_manufacturer = cd->cd_Rom.er_Manufacturer;
589      hw->hw_product	  = cd->cd_Rom.er_Product;
590
591      switch (hw->hw_manufacturer)
592        {
593        case MANUF_CBM_1:
594          switch (hw->hw_product)
595            {
596            case PROD_CBM_1_A2088:
597              hw->hw_type = B_ZORROII | D_MISC;
598              break;
599
600            default:
601              continue;
602            }
603
604        case MANUF_UNILOWELL:
605          switch (hw->hw_product)
606            {
607            case PROD_UNILOWELL_A2410:
608              hw->hw_type = B_ZORROII | D_BITMAP;
609              break;
610
611            default:
612              continue;
613            }
614
615        default:
616          continue;
617	}
618
619      hw++;
620    }
621}
622
623#if 0
624/*
625 * Allocate/deallocate a cache-inhibited range of kernel virtual address
626 * space mapping the indicated physical address range [pa - pa+size)
627 */
628caddr_t
629iomap(pa, size)
630	caddr_t pa;
631	int size;
632{
633	int ix, npf;
634	caddr_t kva;
635
636#ifdef DEBUG
637	if (((int)pa & PGOFSET) || (size & PGOFSET))
638		panic("iomap: unaligned");
639#endif
640	npf = btoc(size);
641	ix = rmalloc(extiomap, npf);
642	if (ix == 0)
643		return(0);
644	kva = extiobase + ctob(ix-1);
645	physaccess(kva, pa, size, PG_RW|PG_CI);
646	return(kva);
647}
648
649iounmap(kva, size)
650	caddr_t kva;
651	int size;
652{
653	int ix;
654
655#ifdef DEBUG
656	if (((int)kva & PGOFSET) || (size & PGOFSET))
657		panic("iounmap: unaligned");
658	if (kva < extiobase || kva >= extiobase + ctob(EIOMAPSIZE))
659		panic("iounmap: bad address");
660#endif
661	physunaccess(kva, size);
662	ix = btoc(kva - extiobase) + 1;
663	rmfree(extiomap, btoc(size), ix);
664}
665#endif
666
667#if NCD > 0
668#include "../dev/cdvar.h"
669
670find_cdevices()
671{
672	register struct cddevice *cd;
673
674	for (cd = cddevice; cd->cd_unit >= 0; cd++) {
675		/*
676		 * XXX
677		 * Assign disk index first so that init routine
678		 * can use it (saves having the driver drag around
679		 * the cddevice pointer just to set up the dk_*
680		 * info in the open routine).
681		 */
682		if (dkn < DK_NDRIVE)
683			cd->cd_dk = dkn++;
684		else
685			cd->cd_dk = -1;
686		if (cdinit(cd))
687			printf("cd%d configured\n", cd->cd_unit);
688		else if (cd->cd_dk >= 0) {
689			cd->cd_dk = -1;
690			dkn--;
691		}
692	}
693}
694#endif
695
696#if 0
697isrinit()
698{
699	register int i;
700
701	for (i = 0; i < NISR; i++)
702		isrqueue[i].isr_forw = isrqueue[i].isr_back = &isrqueue[i];
703}
704
705void
706isrlink(isr)
707	register struct isr *isr;
708{
709	int i = ISRIPL(isr->isr_ipl);
710
711	if (i < 0 || i >= NISR) {
712		printf("bad IPL %d\n", i);
713		panic("configure");
714	}
715	insque(isr, isrqueue[i].isr_back);
716}
717#endif
718
719/*
720 * Configure swap space and related parameters.
721 */
722swapconf()
723{
724	register struct swdevt *swp;
725	register int nblks;
726
727	for (swp = swdevt; swp->sw_dev; swp++)
728	  {
729		if (bdevsw[major(swp->sw_dev)].d_psize) {
730			nblks =
731			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
732			if (nblks != -1 &&
733			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
734			      {
735				swp->sw_nblks = nblks;
736/*				printf ("swap: dev %x = %d\n", swp->sw_dev, nblks);*/
737			      }
738		}
739	  }
740	dumpconf();
741
742	printf ("\n");
743}
744
745#define	DOSWAP			/* Change swdevt and dumpdev too */
746u_long	bootdev;		/* should be dev_t, but not until 32 bits */
747
748static	char devname[][2] = {
749	0,0,		/* 0 = ct */
750	0,0,		/* 1 = xx */
751	'r','d',	/* 2 = rd */
752	0,0,		/* 3 = sw */
753	's','d',	/* 4 = sd */
754};
755
756#define	PARTITIONMASK	0x7
757#define	PARTITIONSHIFT	3
758
759/*
760 * Attempt to find the device from which we were booted.
761 * If we can do so, and not instructed not to do so,
762 * change rootdev to correspond to the load device.
763 */
764setroot()
765{
766	register struct amiga_ctlr *ac;
767	register struct amiga_device *ad;
768	int  majdev, mindev, unit, part, adaptor;
769	dev_t temp, orootdev;
770	struct swdevt *swp;
771
772/*	printf ("setroot: boothowto = 0x%x, bootdev = 0x%x\n", boothowto, bootdev);*/
773
774	if (boothowto & RB_DFLTROOT ||
775	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
776		return;
777	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
778	if (majdev > sizeof(devname) / sizeof(devname[0]))
779		return;
780	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
781	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
782	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
783	/*
784	 * First, find the controller type which support this device.
785	 */
786	for (ad = amiga_dinit; ad->amiga_driver; ad++)
787		if (ad->amiga_driver->d_name[0] == devname[majdev][0] &&
788		    ad->amiga_driver->d_name[1] == devname[majdev][1])
789			break;
790	if (ad->amiga_driver == 0)
791		return;
792	/*
793	 * Next, find the controller of that type corresponding to
794	 * the adaptor number.
795	 */
796	for (ac = amiga_cinit; ac->amiga_driver; ac++)
797		if (ac->amiga_alive && ac->amiga_unit == adaptor &&
798		    ac->amiga_driver == ad->amiga_cdriver)
799			break;
800	if (ac->amiga_driver == 0)
801		return;
802	/*
803	 * Finally, find the device in question attached to that controller.
804	 */
805	for (ad = amiga_dinit; ad->amiga_driver; ad++)
806		if (ad->amiga_alive && ad->amiga_slave == unit &&
807		    ad->amiga_cdriver == ac->amiga_driver &&
808		    ad->amiga_ctlr == ac->amiga_unit)
809			break;
810	if (ad->amiga_driver == 0)
811		return;
812	mindev = ad->amiga_unit;
813	/*
814	 * Form a new rootdev
815	 */
816	mindev = (mindev << PARTITIONSHIFT) + part;
817	orootdev = rootdev;
818	rootdev = makedev(majdev, mindev);
819	/*
820	 * If the original rootdev is the same as the one
821	 * just calculated, don't need to adjust the swap configuration.
822	 */
823	if (rootdev == orootdev)
824		return;
825
826	printf("Changing root device to %c%c%d%c\n",
827		devname[majdev][0], devname[majdev][1],
828		mindev >> PARTITIONSHIFT, part + 'a');
829
830#ifdef DOSWAP
831	mindev &= ~PARTITIONMASK;
832	for (swp = swdevt; swp->sw_dev; swp++) {
833		if (majdev == major(swp->sw_dev) &&
834		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
835			temp = swdevt[0].sw_dev;
836			swdevt[0].sw_dev = swp->sw_dev;
837			swp->sw_dev = temp;
838			break;
839		}
840	}
841	if (swp->sw_dev == 0)
842		return;
843
844	/*
845	 * If dumpdev was the same as the old primary swap
846	 * device, move it to the new primary swap device.
847	 */
848	if (temp == dumpdev)
849		dumpdev = swdevt[0].sw_dev;
850#endif
851}
852