/* autoconf.c 1.11 87/01/04 */
* Setup the system to run on the current machine.
* Configure() is called at boot time and initializes the vba
* device tables and the memory controller monitoring. Available
* devices are determined (from possibilities mentioned in ioconf.c),
* and the drivers are initialized.
#include "../tahoe/pte.h"
#include "../tahoe/mem.h"
#include "../tahoe/mtpr.h"
#include "../tahoe/scb.h"
#include "../tahoevba/vbavar.h"
#include "../tahoevba/vbaparam.h"
* The following several variables are related to
* the configuration process, and are used in initializing
int dkn
; /* number of iostat dk numbers assigned so far */
int cold
; /* cold start flag initialized in locore.s */
* This allocates the space for the per-vba information.
struct vba_hd vba_hd
[NVBA
];
* Determine i/o configuration for a machine.
vbafind(numvba
, (caddr_t
)&vmem
, VMEMmap
);
* Write protect the scb. It is strange
* that this code is here, but this is as soon
* as we are done mucking with it, and the
* write-enable was done in assembly language
* to which we will never return.
ip
= (int *)&Sysmap
[2]; *ip
&= ~PG_PROT
; *ip
|= PG_KR
;
mtpr(TBIS
, Sysbase
+2*NBPG
);
if ((boothowto
& RB_ASKNAME
) == 0)
* Configure swap area and related system
* parameter based on device(s) used.
* Make the controllers accessible at physical address phys
* by mapping kernel ptes starting at pte.
register struct pte
*pte
;
register unsigned v
= btop(iobase
);
*(int *)pte
++ = PG_V
|PG_KW
|v
++;
* Fixctlrmask fixes the masks of the driver ctlr routines
* which otherwise save r11 and r12 where the interrupt and br
* level are passed through.
register struct vba_ctlr
*vm
;
register struct vba_device
*vi
;
register struct vba_driver
*vd
;
#define phys(a,b) ((b)(((int)(a))&~0xc0000000))
vm
= phys(vbminit
, struct vba_ctlr
*);
for (; vd
= phys(vm
->um_driver
, struct vba_driver
*); vm
++)
*phys(vd
->ud_probe
, short *) &= ~0x1800;
vi
= phys(vbdinit
, struct vba_device
*);
for (; vd
= phys(vi
->ui_driver
, struct vba_driver
*); vi
++)
*phys(vd
->ud_probe
, short *) &= ~0x1800;
* Find devices on the VERSAbus.
* Uses per-driver routine to see who is on the bus
* and then fills in the tables, with help from a per-driver
* slave initialization routine.
vbafind(vban
, vumem
, memmap
)
register int br
, cvec
; /* must be r12, r11 */
register struct vba_device
*ui
;
register struct vba_ctlr
*um
;
caddr_t valloc
, zmemall();
extern long catcher
[SCB_LASTIV
*2];
* Make the controllers accessible at physical address phys
* by mapping kernel ptes starting at pte.
vbaccess(memmap
, (caddr_t
)VBIOBASE
, VBIOSIZE
);
printf("vba%d at %x\n", vban
, VBIOBASE
);
* Setup scb device entries to point into catcher array.
for (i
= 0; i
< SCB_LASTIV
; i
++)
scb
.scb_devint
[i
] = (int (*)())&catcher
[i
*2];
* Set last free interrupt vector for devices with
* programmable interrupt vectors. Use is to decrement
* this number and use result as interrupt vector.
vhp
->vh_lastiv
= SCB_LASTIV
;
* Grab some memory to record the address space we allocate,
* so we can be sure not to place two devices at the same address.
* We could use just 1/8 of this (we only want a 1 bit flag) but
* we are going to give it back anyway, and that would make the
* code here bigger (which we can't give back), so ...
valloc
= zmemall(memall
, ctob(VBIOSIZE
));
if (valloc
== (caddr_t
)0)
panic("no mem for vbafind");
* Check each VERSAbus mass storage controller.
* For each one which is potentially on this vba,
* see if it is really there, and if it is record it and
* then go looking for slaves.
#define vbaddr(off) (u_short *)(vumem + vboff(off))
for (um
= vbminit
; udp
= um
->um_driver
; um
++) {
if (um
->um_vbanum
!= vban
&& um
->um_vbanum
!= '?')
* Use the particular address specified first,
* or if it is given as "0", if there is no device
* at that address, try all the standard addresses
* in the driver until we find it.
addr
= (long)um
->um_addr
;
for (ap
= udp
->ud_addr
; addr
|| (addr
= *ap
++); addr
= 0) {
cvec
= SCB_LASTIV
, cold
&= ~0x2;
i
= (*udp
->ud_probe
)(reg
, um
);
printf("%s%d at vba%d csr %x ",
udp
->ud_mname
, um
->um_ctlr
, vban
, addr
);
if (cvec
< 0 && vhp
->vh_lastiv
== cvec
) {
printf("no space for vector(s)\n");
if (cvec
== SCB_LASTIV
) {
printf("didn't interrupt\n");
printf("vec %x, ipl %x\n", cvec
, br
);
csralloc(valloc
, addr
, i
);
um
->um_addr
= (caddr_t
)reg
;
udp
->ud_minfo
[um
->um_ctlr
] = um
;
for (ivec
= um
->um_intr
; *ivec
; ivec
++)
((long *)&scb
)[cvec
++] = (long)*ivec
;
for (ui
= vbdinit
; ui
->ui_driver
; ui
++) {
if (ui
->ui_driver
!= udp
|| ui
->ui_alive
||
ui
->ui_ctlr
!= um
->um_ctlr
&& ui
->ui_ctlr
!= '?' ||
ui
->ui_vbanum
!= vban
&& ui
->ui_vbanum
!= '?')
if ((*udp
->ud_slave
)(ui
, reg
)) {
ui
->ui_ctlr
= um
->um_ctlr
;
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= (caddr_t
)addr
;
if (ui
->ui_dk
&& dkn
< DK_NDRIVE
)
/* ui_type comes from driver */
udp
->ud_dinfo
[ui
->ui_unit
] = ui
;
printf("%s%d at %s%d slave %d",
udp
->ud_dname
, ui
->ui_unit
,
udp
->ud_mname
, um
->um_ctlr
,
* Now look for non-mass storage peripherals.
for (ui
= vbdinit
; udp
= ui
->ui_driver
; ui
++) {
if (ui
->ui_vbanum
!= vban
&& ui
->ui_vbanum
!= '?' ||
ui
->ui_alive
|| ui
->ui_slave
!= -1)
addr
= (long)ui
->ui_addr
;
for (ap
= udp
->ud_addr
; addr
|| (addr
= *ap
++); addr
= 0) {
cvec
= SCB_LASTIV
, cold
&= ~0x2;
i
= (*udp
->ud_probe
)(reg
, ui
);
printf("%s%d at vba%d csr %x ",
ui
->ui_driver
->ud_dname
, ui
->ui_unit
, vban
, addr
);
if (cvec
< 0 && vhp
->vh_lastiv
== cvec
) {
printf("no space for vector(s)\n");
if (cvec
== SCB_LASTIV
) {
printf("didn't interrupt\n");
printf("vec %x, ipl %x\n", cvec
, br
);
for (ivec
= ui
->ui_intr
; *ivec
; ivec
++)
((long *)&scb
)[cvec
++] = (long)*ivec
;
printf("no interrupts\n");
csralloc(valloc
, addr
, i
);
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= (caddr_t
)addr
;
/* ui_type comes from driver */
udp
->ud_dinfo
[ui
->ui_unit
] = ui
;
wmemfree(valloc
, ctob(VBIOSIZE
));
* Mark addresses starting at addr and continuing
* size bytes as allocated in the map.
* Warn if the new allocation overlaps a previous allocation.
csralloc(valloc
, addr
, size
)
p
= &valloc
[vboff(addr
+size
)];
"WARNING: device registers overlap those for a previous device\n");
* Tahoe VERSAbus adapator support routines.
caddr_t vbcur
= (caddr_t
)&vbbase
;
* Allocate page tables for mapping intermediate i/o buffers.
* Called by device drivers during autoconfigure.
vbmapalloc(npf
, ppte
, putl
)
if (vbcur
+ npf
*NBPG
>= (caddr_t
)&vbend
)
caddr_t vbmcur
= (caddr_t
)&vmem1
;
* Allocate page tables and map VERSAbus i/o space.
* Called by device drivers during autoconfigure.
vbmemalloc(npf
, addr
, ppte
, putl
)
if (vbmcur
+ npf
*NBPG
>= (caddr_t
)&vmemend
)
vbaccess(*ppte
, addr
, npf
); /* map i/o space */
* Configure swap space and related parameters.
register struct swdevt
*swp
;
for (swp
= swdevt
; swp
->sw_dev
; swp
++)
if (bdevsw
[major(swp
->sw_dev
)].d_psize
) {
(*bdevsw
[major(swp
->sw_dev
)].d_psize
)(swp
->sw_dev
);
if (swp
->sw_nblks
== 0 || swp
->sw_nblks
> nblks
)
if (dumplo
== 0 && bdevsw
[major(dumpdev
)].d_psize
)
dumplo
= (*bdevsw
[major(dumpdev
)].d_psize
)(dumpdev
) - physmem
;
#define DOSWAP /* change swdevt, argdev, and dumpdev too */
u_long bootdev
; /* should be dev_t, but not until 32 bits */
static char devname
[][2] = {
#define PARTITIONMASK 0x7
* Attempt to find the device from which we were booted.
* If we can do so, and not instructed not to do so,
* change rootdev to correspond to the load device.
int majdev
, mindev
, unit
, part
, adaptor
;
if (boothowto
& RB_DFLTROOT
||
(bootdev
& B_MAGICMASK
) != (u_long
)B_DEVMAGIC
)
majdev
= (bootdev
>> B_TYPESHIFT
) & B_TYPEMASK
;
if (majdev
> sizeof(devname
) / sizeof(devname
[0]))
adaptor
= (bootdev
>> B_ADAPTORSHIFT
) & B_ADAPTORMASK
;
part
= (bootdev
>> B_PARTITIONSHIFT
) & B_PARTITIONMASK
;
unit
= (bootdev
>> B_UNITSHIFT
) & B_UNITMASK
;
* Search Versabus devices.
* WILL HAVE TO DISTINGUISH VME/VERSABUS SOMETIME
register struct vba_device
*vbap
;
for (vbap
= vbdinit
; vbap
->ui_driver
; vbap
++)
if (vbap
->ui_alive
&& vbap
->ui_slave
== unit
&&
vbap
->ui_vbanum
== adaptor
&&
vbap
->ui_driver
->ud_dname
[0] == devname
[majdev
][0] &&
vbap
->ui_driver
->ud_dname
[1] == devname
[majdev
][1])
if (vbap
->ui_driver
== 0)
mindev
= (mindev
<< PARTITIONSHIFT
) + part
;
rootdev
= makedev(majdev
, mindev
);
* If the original rootdev is the same as the one
* just calculated, don't need to adjust the swap configuration.
printf("changing root device to %c%c%d%c\n",
devname
[majdev
][0], devname
[majdev
][1],
mindev
>> PARTITIONSHIFT
, part
+ 'a');
mindev
&= ~PARTITIONMASK
;
for (swp
= swdevt
; swp
->sw_dev
; swp
++) {
if (majdev
== major(swp
->sw_dev
) &&
mindev
== (minor(swp
->sw_dev
) & ~PARTITIONMASK
)) {
swdevt
[0].sw_dev
= swp
->sw_dev
;
* If argdev and dumpdev were the same as the old primary swap
* device, move them to the new primary swap device.
dumpdev
= swdevt
[0].sw_dev
;
argdev
= swdevt
[0].sw_dev
;