* Copyright (c) 1982,1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)autoconf.c 7.15 (Berkeley) %G%
* Setup the system to run on the current machine.
* Configure() is called at boot time and initializes the uba and mba
* device tables and the memory controller monitoring. Available
* devices are determined (from possibilities mentioned in ioconf.c),
* and the drivers are initialized.
#include "kra.h" /* XXX wrong file */
#include "../vaxbi/bireg.h"
#include "../vaxmba/mbareg.h"
#include "../vaxmba/mbavar.h"
#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"
* The following several variables are related to
* the configuration process, and are used in initializing
int cold
; /* if 1, still working on cold-start */
int dkn
; /* number of iostat dk numbers assigned so far */
int cpuspeed
= 1; /* relative cpu speed */
* Addresses of the (locore) routines which bootstrap us from
* hardware traps to C code. Filled into the system control block
* RIDICULOUS! CONFIG SHOULD GENERATE AN ioconf.h FOR US, with
* mba glue also in `glue.s'. (Unibus adapter glue is special, though.)
int (*mbaintv
[4])() = { Xmba0int
, Xmba1int
, Xmba2int
, Xmba3int
};
Need to expand the table
for more than
4 massbus adaptors
#if defined(VAX780) || defined(VAX8600)
Xua0int
, Xua1int
, Xua2int
, Xua3int
,
Xua4int
, Xua5int
, Xua6int
, Xua7int
,
Need to expand the table
for more than
8 unibus adaptors
/* kdb50 driver does not appear in udminit[] (not without csr!) */
int Xkdbintr0(); /* generated by autoconf */
int (*kdbintv
[])() = { Xkdbintr0
};
Need to expand the table
for more than
1 KDB adapter
* This allocates the space for the per-uba information,
* such as buffered data path usage.
struct uba_hd uba_hd
[NUBA
];
* Determine mass storage and memory configuration for a machine.
* Get cpu type, and then switch out to machine specific procedures
* which will probe adaptors to see what is out there.
register struct percpu
*ocp
;
cpusid
.cpusid
= mfpr(SID
);
switch (cpusid
.cpuany
.cp_type
) {
printf("VAX 8600, serial# %d(%d), hardware ECO level %d(%d)\n",
cpusid
.cpu780
.cp_sno
, cpusid
.cpu780
.cp_plant
,
cpusid
.cpu780
.cp_eco
>> 4, cpusid
.cpu780
.cp_eco
);
VAX 82%c0, hardware rev %d, ucode patch rev %d, sec patch %d, ucode rev %d\n",
cpusid
.cpu8200
.cp_5
? '5' : '0',
cpusid
.cpu8200
.cp_hrev
, cpusid
.cpu8200
.cp_patch
,
cpusid
.cpu8200
.cp_secp
, cpusid
.cpu8200
.cp_urev
);
VAX 11/78%c, serial# %d(%d), hardware ECO level %d(%d)\n",
cpusid
.cpu780
.cp_5
? '5' : '0',
cpusid
.cpu780
.cp_sno
, cpusid
.cpu780
.cp_plant
,
cpusid
.cpu780
.cp_eco
>> 4, cpusid
.cpu780
.cp_eco
);
printf("VAX 11/750, hardware rev %d, ucode rev %d\n",
cpusid
.cpu750
.cp_hrev
, cpusid
.cpu750
.cp_urev
);
printf("VAX 11/730, ucode rev %d\n", cpusid
.cpu730
.cp_urev
);
for (ocp
= percpu
; ocp
->pc_cputype
; ocp
++)
if (ocp
->pc_cputype
== cpusid
.cpuany
.cp_type
) {
cpuspeed
= ocp
->pc_cpuspeed
;
if (cpuops
->cpu_init
!= NULL
)
* Write protect the scb and UNIBUS interrupt vectors.
* 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.
for (ip
= kvtopte(scb
); ip
< kvtopte(eUNIvec
); ip
++) {
if ((boothowto
& RB_ASKNAME
) == 0)
* Configure swap area and related system
* parameter based on device(s) used.
printf("cpu type %d not configured\n", cpusid
.cpuany
.cp_type
);
#if VAX8600 || VAX780 || VAX750 || VAX730
int nexnum
; /* current nexus number */
int nsbi
; /* current sbi number */
int numkdb
; /* current ``kdb'' number */
int bi_nodes
; /* XXX remembers found bi nodes */
* Probe the main IO bus(es).
* The percpu structure gives us a handle on the addresses and/or types.
register struct percpu
*pcpu
;
register struct iobus
*iob
;
for (iob
= pcpu
->pc_io
; ioanum
< pcpu
->pc_nioa
; ioanum
++, iob
++) {
probeqbus((struct qbus
*)iob
->io_details
);
#if VAX780 || VAX750 || VAX730
probenexi((struct nexusconnect
*)iob
->io_details
);
probe_bi((struct bibus
*)iob
->io_details
);
"IO adaptor %d, type %d, at address 0x%x is unsupported\n",
ioanum
, iob
->io_type
, iob
->io_addr
);
printf("IO adaptor %d, type %d, is unsupported\n",
register struct iobus
*iob
;
register struct ioa
*ioap
;
struct sbia_regs
*sbiaregs
;
int sbi1fail(), sbi1alert(), sbi1fault(), sbi1err();
ioaccess(iob
->io_addr
, Ioamap
[ioanum
], iob
->io_size
);
if (badaddr((caddr_t
)ioap
, 4))
ioacsr
.ioa_csr
= ioap
->ioacsr
.ioa_csr
;
type
= ioacsr
.ioa_type
& IOA_TYPMSK
;
printf("SBIA%d at IO adaptor %d address 0x%x\n",
nsbi
, ioanum
, iob
->io_addr
);
/* I AM NOT SURE THESE ARE IN THE SAME PLACES */
scb
[1].scb_sbifail
= scbentry(sbi1fail
, SCB_ISTACK
);
/* maybe not sbifail, maybe scb1.scb_cmrd */
/* but how can I find out without a broken SBIA1? */
scb
[1].scb_sbialert
= scbentry(sbi1alert
, SCB_ISTACK
);
scb
[1].scb_sbifault
= scbentry(sbi1fault
, SCB_ISTACK
);
scb
[1].scb_sbierr
= scbentry(sbi1err
, SCB_ISTACK
);
probenexi((struct nexusconnect
*)iob
->io_details
);
sbiaregs
= (struct sbia_regs
*)ioap
;
sbiaregs
->sbi_errsum
= -1;
sbiaregs
->sbi_error
= 0x1000;
sbiaregs
->sbi_fltsts
= 0xc0000;
printf("IOA%d at address 0x%x is unsupported (type = 0x%x)\n",
ioanum
, iob
->io_addr
, ioacsr
.ioa_type
);
#if VAX8600 || VAX780 || VAX750 || VAX730
* Probe nexus space, finding the interconnects
* and setting up and probing mba's and uba's for devices.
register struct nexusconnect
*pnc
;
register struct nexus
*nxv
;
struct nexus
*nxp
= pnc
->psb_nexbase
;
ioaccess((caddr_t
)nxp
, Nexmap
[nsbi
* NNEXSBI
],
pnc
->psb_nnexus
* sizeof(struct nexus
));
nxv
= &nexus
[nsbi
* NNEXSBI
];
for (nexnum
= 0; nexnum
< pnc
->psb_nnexus
; nexnum
++, nxp
++, nxv
++) {
if (badaddr((caddr_t
)nxv
, 4))
if (pnc
->psb_nextype
&& pnc
->psb_nextype
[nexnum
] != NEX_ANY
)
nexcsr
.nex_csr
= pnc
->psb_nextype
[nexnum
];
if (nexcsr
.nex_csr
&NEX_APD
)
switch (nexcsr
.nex_type
) {
printf("mba%d at tr%d\n", nummba
, nexnum
);
printf("%d mba's", ++nummba
);
printf("uba%d at tr%d\n", numuba
, nexnum
);
printf("%d uba's", ++numuba
);
if (numuba
>= 2 && cpu
== VAX_750
) {
printf("More than 2 UBA's");
#if defined(VAX780) || defined(VAX8600)
if (cpu
== VAX_780
|| cpu
== VAX_8600
)
setscbnex(ubaintv
[numuba
]);
i
= nexcsr
.nex_type
- NEX_UBA0
;
probeuba((struct uba_regs
*)nxv
, (struct uba_regs
*)nxp
,
/* there can be more than one... are there other codes??? */
printf("mcr%d at tr%d\n", nmcr
, nexnum
);
printf("%d mcr's", ++nmcr
);
/* only ka780 code looks at type */
mcraddr
[nmcr
++] = (caddr_t
)nxv
;
printf("mcr%d (el) at tr%d\n", nmcr
, nexnum
);
printf("%d mcr's", ++nmcr
);
mcraddr
[nmcr
++] = (caddr_t
)nxv
;
if (nexcsr
.nex_type
!= NEX_MEM64I
&&
nexcsr
.nex_type
!= NEX_MEM256I
)
printf("mcr%d (eu) at tr%d\n", nmcr
, nexnum
);
printf("%d mcr's", ++nmcr
);
mcraddr
[nmcr
++] = (caddr_t
)nxv
;
printf("nexus type %x", nexcsr
.nex_type
);
printf(" unsupported (at tr %d)\n", nexnum
);
printf(" not configured\n");
register struct scb
*scbp
= &scb
[nsbi
];
scbp
->scb_ipl14
[nexnum
] = scbp
->scb_ipl15
[nexnum
] =
scbp
->scb_ipl16
[nexnum
] = scbp
->scb_ipl17
[nexnum
] =
scbentry(fn
, SCB_ISTACK
);
* THIS DEPENDS ON BI SPACE == NEXUS SPACE
* THIS WILL NOT WORK FOR MULTIPLE BIs
register struct bibus
*p
;
register struct bi_node
*biv
, *bip
;
/* must ignore BI errors while configuring */
ioaccess((caddr_t
)bip
, Nexmap
[0], sizeof(*bip
) * NNODEBI
);/* XXX */
printf("vaxbi0 at address 0x%x\n", bip
);
biv
= (struct bi_node
*) &nexus
[0]; /* XXX */
for (node
= 0; node
< NNODEBI
; node
++, bip
++, biv
++) {
if (badaddr((caddr_t
)biv
, 4))
bi_nodes
|= 1 << node
; /* XXX */
dtype
= biv
->biic
.bi_dtype
;
biv
->biic
.bi_ber
= ~(BIBER_MBZ
|BIBER_NMR
|BIBER_UPEN
);
int cp5
= biv
->biic
.bi_revs
& 0x8000 ? '5' : '0';
printf("slave ka82%c cpu", cp5
);
printf("ka82%c cpu at node %x\n", cp5
, node
);
biv
->biic
.bi_intrdes
= 1 << mastercpu
;
biv
->biic
.bi_csr
|= BICSR_SEIE
| BICSR_HEIE
;
if (numuba
>= NUBA
|| /*XXX*/numuba
> 2) {
printf("%d uba's", ++numuba
);
printf("uba%d at node %x\n", numuba
, node
);
* Run a self test reset to drop any `old' errors,
* so that they cannot cause a BI bus error.
(void) bi_selftest(&biv
->biic
);
* Enable interrupts. DWBUAs must have
biv
->biic
.bi_intrdes
= 1 << mastercpu
;
biv
->biic
.bi_csr
= (biv
->biic
.bi_csr
&~BICSR_ARB_MASK
) |
probeuba((struct uba_regs
*)biv
, (struct uba_regs
*)bip
,
(caddr_t
)UMEM8200(node
));
printf("mcr%d at node %x\n", nmcr
, node
);
printf("%d mcr's", ++nmcr
);
mcraddr
[nmcr
++] = (caddr_t
)biv
;
biv
->biic
.bi_intrdes
= 1 << mastercpu
;
biv
->biic
.bi_csr
|= BICSR_SEIE
| BICSR_HEIE
;
printf("%d kdb's", ++numkdb
);
printf("kdb%d at node %x\n", numkdb
, node
);
kdbconfig(numkdb
, (struct biiregs
*)biv
,
(int)&scb
[0].scb_ipl15
[node
] - (int)&scb
[0]);
scbentry(kdbintv
[numkdb
], SCB_ISTACK
);
printf("debna/debnk ethernet");
printf("node type 0x%x ", dtype
);
printf(" unsupported (at node %x)\n", node
);
printf(" not configured (at node %x)\n", node
);
biv
->biic
.bi_eintrcsr
= BIEIC_IPL17
|
(int)&scb
[0].scb_bierr
- (int)&scb
[0];
/* but bi reset will need to restore this */
* Find drives attached to a particular KDB50.
extern struct uba_driver kdbdriver
;
register struct uba_device
*ui
;
register struct uba_driver
*udp
= &kdbdriver
;
for (ui
= ubdinit
; ui
->ui_driver
; ui
++) {
/* ui->ui_ubanum is trash */
if (ui
->ui_driver
!= udp
|| ui
->ui_alive
||
ui
->ui_ctlr
!= kdbnum
&& ui
->ui_ctlr
!= '?')
if ((*udp
->ud_slave
)(ui
) == 0) {
/* make these invalid so we can see if someone uses them */
/* might as well make each one different too */
ui
->ui_hd
= (struct uba_hd
*)0xc0000010;
ui
->ui_addr
= (caddr_t
)0xc0000014;
ui
->ui_physaddr
= (caddr_t
)0xc0000018;
ui
->ui_mi
= (struct uba_ctlr
*)0xc000001c;
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\n",
udp
->ud_dname
, ui
->ui_unit
,
udp
->ud_mname
, ui
->ui_ctlr
, ui
->ui_slave
);
struct mba_device
*mbaconfig();
* Find devices attached to a particular mba
* and look for each device found in the massbus
register struct mba_regs
*mdp
;
register struct mba_drv
*mbd
;
register struct mba_device
*mi
;
register struct mba_slave
*ms
;
mdp
= (struct mba_regs
*)nxv
;
mba_hd
[nummba
].mh_mba
= mdp
;
mba_hd
[nummba
].mh_physmba
= (struct mba_regs
*)nxp
;
setscbnex(mbaintv
[nummba
]);
for (mbd
= mdp
->mba_drv
, dn
= 0; mbd
< &mdp
->mba_drv
[8]; mbd
++, dn
++) {
if ((mbd
->mbd_ds
&MBDS_DPR
) == 0)
mdp
->mba_sr
|= MBSR_NED
; /* si kludge */
dt
= mbd
->mbd_dt
& 0xffff;
if (mdp
->mba_sr
&MBSR_NED
)
continue; /* si kludge */
#define qeq(a, b) ( a == b || a == '?' )
if ((mi
= mbaconfig(&fnd
, dt
)) && (dt
& MBDT_TAP
))
for (sn
= 0; sn
< 8; sn
++) {
for (ms
= mbsinit
; ms
->ms_driver
; ms
++)
if (ms
->ms_driver
== mi
->mi_driver
&&
qeq(ms
->ms_ctlr
, mi
->mi_unit
) &&
(*ms
->ms_driver
->md_slave
)(mi
, ms
, sn
)) {
printf("%s%d at %s%d slave %d\n"
, ms
->ms_driver
->md_sname
, mi
->mi_driver
->md_dname
ms
->ms_ctlr
= mi
->mi_unit
;
* Have found a massbus device;
* see if it is in the configuration table.
* If so, fill in its data.
register struct mba_device
*ni
;
register struct mba_device
*mi
;
register struct mba_hd
*mh
;
for (mi
= mbdinit
; mi
->mi_driver
; mi
++) {
tp
= mi
->mi_driver
->md_type
;
for (mi
->mi_type
= 0; *tp
; tp
++, mi
->mi_type
++)
if (*tp
== (type
&MBDT_TYPE
))
#define match(fld) (ni->fld == mi->fld || mi->fld == '?')
if (!match(mi_drive
) || !match(mi_mbanum
))
printf("%s%d at mba%d drive %d",
mi
->mi_driver
->md_dname
, mi
->mi_unit
,
ni
->mi_mbanum
, ni
->mi_drive
);
mh
= &mba_hd
[ni
->mi_mbanum
];
mh
->mh_mbip
[ni
->mi_drive
] = mi
;
mi
->mi_drv
= &mi
->mi_mba
->mba_drv
[ni
->mi_drive
];
mi
->mi_mbanum
= ni
->mi_mbanum
;
mi
->mi_drive
= ni
->mi_drive
;
* If drive has never been seen before,
* give it a dkn for statistics.
if (mi
->mi_driver
->md_info
[mi
->mi_unit
] == 0) {
mi
->mi_driver
->md_info
[mi
->mi_unit
] = mi
;
if (mi
->mi_dk
&& dkn
< DK_NDRIVE
)
(*mi
->mi_driver
->md_attach
)(mi
);
* Fixctlrmask fixes the masks of the driver ctlr routines
* which otherwise save r10 and r11 where the interrupt and br
* level are passed through.
register struct uba_ctlr
*um
;
register struct uba_device
*ui
;
register struct uba_driver
*ud
;
#define phys(a,b) ((b)(((int)(a))&0x7fffffff))
for (um
= ubminit
; ud
= phys(um
->um_driver
, struct uba_driver
*); um
++)
*phys(ud
->ud_probe
, short *) &= ~0xc00;
for (ui
= ubdinit
; ud
= phys(ui
->ui_driver
, struct uba_driver
*); ui
++)
*phys(ud
->ud_probe
, short *) &= ~0xc00;
register struct uba_hd
*uhp
= &uba_hd
[numuba
];
ioaccess((caddr_t
)qb
->qb_map
, Nexmap
[0],
qb
->qb_memsize
* sizeof (struct pte
));
uhp
->uh_type
= qb
->qb_type
;
uhp
->uh_uba
= (struct uba_regs
*)0xc0000000; /* no uba adaptor regs */
uhp
->uh_mr
= (struct pte
*)&nexus
[0];
* The map registers start right at 20088000 on the
* ka630, so we have to subtract out the 2k offset to make the
uhp
->uh_physuba
= (struct uba_regs
*)(((u_long
)qb
->qb_map
)-0x800);
uhp
->uh_memsize
= qb
->qb_memsize
;
ioaccess(qb
->qb_maddr
, UMEMmap
[numuba
], uhp
->uh_memsize
* NBPG
);
uhp
->uh_mem
= umem
[numuba
];
* The I/O page is mapped to the 8K of the umem address space
* immediately after the memory section that is mapped.
ioaccess(qb
->qb_iopage
, UMEMmap
[numuba
] + uhp
->uh_memsize
,
uhp
->uh_iopage
= umem
[numuba
] + (uhp
->uh_memsize
* NBPG
);
unifind(uhp
, qb
->qb_iopage
);
probeuba(vubp
, pubp
, pumem
)
struct uba_regs
*vubp
, *pubp
;
register struct uba_hd
*uhp
= &uba_hd
[numuba
];
* Save virtual and physical addresses of adaptor.
panic("unknown UBA type");
uhp
->uh_mr
= vubp
->uba_map
;
uhp
->uh_memsize
= UBAPAGES
;
ioaccess(pumem
, UMEMmap
[numuba
], (UBAPAGES
+ UBAIOPAGES
) * NBPG
);
uhp
->uh_mem
= umem
[numuba
];
uhp
->uh_iopage
= umem
[numuba
] + (uhp
->uh_memsize
* NBPG
);
unifind(uhp
, pumem
+ (uhp
->uh_memsize
* NBPG
));
* Find devices on a UNIBUS.
* Uses per-driver routine to set <br,cvec> into <r11,r10>,
* and then fills in the tables, with help from a per-driver
* slave initialization routine.
register int br
, cvec
; /* MUST BE r11, r10 */
* Lint doesn't realize that these
* can be initialized asynchronously
* when devices interrupt.
register int br
= 0, cvec
= 0;
register struct uba_device
*ui
;
register struct uba_ctlr
*um
;
register struct uba_hd
*uhp
= uhp0
;
extern quad catcher
[128];
struct uba_regs
*vubp
= uhp
->uh_uba
;
* Initialize the UNIBUS, by freeing the map
* registers and the buffered data path registers
uhp
->uh_map
= (struct map
*)
malloc((u_long
)(UAMSIZ
* sizeof (struct map
)), M_DEVBUF
,
panic("no mem for unibus map");
bzero((caddr_t
)uhp
->uh_map
, (unsigned)(UAMSIZ
* sizeof (struct map
)));
* Initialize space for the UNIBUS interrupt vectors.
* On the 8600, can't use first slot in UNIvec
* (the vectors for the second SBI overlap it);
* move each set of vectors forward.
uhp
->uh_vec
= UNIvec
[numuba
+ 1];
uhp
->uh_vec
= UNIvec
[numuba
];
for (i
= 0; i
< 128; i
++)
uhp
->uh_vec
[i
] = scbentry(&catcher
[i
], SCB_ISTACK
);
* Set last free interrupt vector for devices with
* programmable interrupt vectors. Use is to decrement
* this number and use result as interrupt vector.
if (uhp
->uh_type
== DWBUA
)
BUA(vubp
)->bua_offset
= (int)uhp
->uh_vec
- (int)&scb
[0];
if (uhp
->uh_type
== DW780
) {
vubp
->uba_sr
= vubp
->uba_sr
;
vubp
->uba_cr
= UBACR_IFS
|UBACR_BRIE
;
* First configure devices that have unibus memory,
* allowing them to allocate the correct map registers.
* Grab some memory to record the umem 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 ...
* One day, someone will make a unibus with something other than
* an 8K i/o address space, & screw this totally.
ualloc
= (caddr_t
)malloc((u_long
)(8 * 1024), M_TEMP
, M_NOWAIT
);
if (ualloc
== (caddr_t
)0)
panic("no mem for unifind");
* Map the first page of UNIBUS i/o
* space to the first page of memory
* for devices which will need to dma
* output to produce an interrupt.
*(int *)(&uhp
->uh_mr
[0]) = UBAMR_MRV
;
#define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off))
* Check each unibus mass storage controller.
* For each one which is potentially on this uba,
* see if it is really there, and if it is record it and
* then go looking for slaves.
for (um
= ubminit
; udp
= um
->um_driver
; um
++) {
if (um
->um_ubanum
!= numuba
&& um
->um_ubanum
!= '?' ||
addr
= (u_short
)um
->um_addr
;
* use the particular address specified first,
* or if it is given as "0", of there is no device
* at that address, try all the standard addresses
* in the driver til we find it
for (ap
= udp
->ud_addr
; addr
|| (addr
= *ap
++); addr
= 0) {
if (ualloc
[ubdevreg(addr
)])
if (badaddr((caddr_t
)reg
, 2))
if (uhp
->uh_type
== DW780
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
i
= (*udp
->ud_probe
)(reg
, um
->um_ctlr
, um
);
if (uhp
->uh_type
== DW780
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
printf("%s%d at uba%d csr %o ",
udp
->ud_mname
, um
->um_ctlr
, numuba
, addr
);
printf("didn't interrupt\n");
printf("vec %o, ipl %x\n", cvec
, br
);
csralloc(ualloc
, addr
, i
);
um
->um_addr
= (caddr_t
)reg
;
udp
->ud_minfo
[um
->um_ctlr
] = um
;
for (cvec
/= 4, ivec
= um
->um_intr
; *ivec
; cvec
++, ivec
++)
uhp
->uh_vec
[cvec
] = scbentry(*ivec
, SCB_ISTACK
);
for (ui
= ubdinit
; ui
->ui_driver
; ui
++) {
if (ui
->ui_driver
!= udp
|| ui
->ui_alive
||
ui
->ui_ctlr
!= um
->um_ctlr
&& ui
->ui_ctlr
!= '?' ||
ui
->ui_ubanum
!= numuba
&& ui
->ui_ubanum
!= '?')
ui
->ui_ctlr
= um
->um_ctlr
;
if ((*udp
->ud_slave
)(ui
, reg
) == 0)
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= pumem
+ ubdevreg(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
, ui
->ui_slave
);
* Now look for non-mass storage peripherals.
for (ui
= ubdinit
; udp
= ui
->ui_driver
; ui
++) {
if (ui
->ui_ubanum
!= numuba
&& ui
->ui_ubanum
!= '?' ||
ui
->ui_alive
|| ui
->ui_slave
!= -1)
addr
= (u_short
)ui
->ui_addr
;
for (ap
= udp
->ud_addr
; addr
|| (addr
= *ap
++); addr
= 0) {
if (ualloc
[ubdevreg(addr
)])
if (badaddr((caddr_t
)reg
, 2))
if (uhp
->uh_type
== DW780
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
i
= (*udp
->ud_probe
)(reg
, ui
);
if (uhp
->uh_type
== DW780
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
printf("%s%d at uba%d csr %o ",
ui
->ui_driver
->ud_dname
, ui
->ui_unit
, numuba
, addr
);
printf("didn't interrupt\n");
printf("vec %o, ipl %x\n", cvec
, br
);
csralloc(ualloc
, addr
, i
);
for (cvec
/= 4, ivec
= ui
->ui_intr
; *ivec
; cvec
++, ivec
++)
uhp
->uh_vec
[cvec
] = scbentry(*ivec
, SCB_ISTACK
);
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= pumem
+ ubdevreg(addr
);
/* ui_type comes from driver */
udp
->ud_dinfo
[ui
->ui_unit
] = ui
;
if (uhp
->uh_type
== DW780
)
uhp
->uh_uba
->uba_cr
= UBACR_IFS
| UBACR_BRIE
|
UBACR_USEFIE
| UBACR_SUEFIE
|
(uhp
->uh_uba
->uba_cr
& 0x7c000000);
printf("Unibus allocation map");
for (i
= 0; i
< 8*1024; ) {
for (n
= 0; n
< 128; n
++)
for (n
= m
= 0; n
< 16; n
++) {
* Mark addresses starting at "addr" and continuing
* "size" bytes as allocated in the map "ualloc".
* Warn if the new allocation overlaps a previous allocation.
csralloc(ualloc
, addr
, size
)
p
= &ualloc
[ubdevreg(addr
+size
)];
"WARNING: device registers overlap those for a previous device!\n");
* Make an IO register area accessible at physical address physa
* by mapping kernel ptes starting at pte.
ioaccess(physa
, pte
, size
)
register struct pte
*pte
;
register int i
= btoc(size
);
register unsigned v
= btop(physa
);
*(int *)pte
++ = PG_V
|PG_KW
|v
++;
* 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
);
(swp
->sw_nblks
== 0 || swp
->sw_nblks
> nblks
))
if (dumplo
== 0 && bdevsw
[major(dumpdev
)].d_psize
)
dumplo
= (*bdevsw
[major(dumpdev
)].d_psize
)(dumpdev
) - physmem
;
register struct swdevt
*swp
;
for (swp
= swdevt
; swp
->sw_dev
; swp
++)
if ((nblks
= psize(swp
->sw_dev
, &swp
->sw_blksize
,
&swp
->sw_bshift
)) != -1 &&
(swp
->sw_nblks
== 0 || swp
->sw_nblks
> nblks
))
if (!cold
) /* In case called for addition of another drive */
nblks
= psize(dumpdev
, (int *)0, (int *)0);
if (nblks
== -1 || nblks
< ctod(physmem
))
dumplo
= nblks
- ctod(physmem
);
* Return size of disk partition in DEV_BSIZE units.
* If needed, return sector size.
psize(dev
, psize
, pshift
)
register int nblks
, bsize
, bshift
;
if ((*bdevsw
[major(dev
)].d_ioctl
)(dev
, DIOCGPART
,
(caddr_t
)&dpart
, FREAD
) == 0)
bsize
= dpart
.disklab
->d_secsize
;
for (nblks
= DEV_BSIZE
/ bsize
; nblks
> 1; nblks
>>= 1)
if (bdevsw
[major(dev
)].d_psize
) {
nblks
= (*bdevsw
[major(dev
)].d_psize
)(dev
);
#define DOSWAP /* Change swdevt, argdev, and dumpdev too */
u_long bootdev
; /* should be dev_t, but not until 32 bits */
static char devname
[][2] = {
'k','r', /* 16 = ra on kdb50 */
#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
, controller
, adaptor
;
if (boothowto
& RB_DFLTROOT
||
(bootdev
& B_MAGICMASK
) != (u_long
)B_DEVMAGIC
)
majdev
= B_TYPE(bootdev
);
if (majdev
>= sizeof(devname
) / sizeof(devname
[0]))
adaptor
= B_ADAPTOR(bootdev
);
controller
= B_CONTROLLER(bootdev
);
part
= B_PARTITION(bootdev
);
if (majdev
== 0) { /* MBA device */
register struct mba_device
*mbap
;
* The MBA number used at boot time is not necessarily the same as the
* MBA number used by the kernel. In order to change the rootdev we need to
* convert the boot MBA number to the kernel MBA number. The address space
* for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number
* on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750.
* Therefore we can search the mba_hd table for the MBA that has the physical
* address corresponding to the boot MBA number.
#define PHYSMBAMASK780 0x7
#define PHYSMBAMASK750 0x3
for (mbap
= mbdinit
; mbap
->mi_driver
; mbap
++)
if (mbap
->mi_alive
&& mbap
->mi_drive
== unit
&&
(((long)mbap
->mi_hd
->mh_physmba
>> PHYSADRSHFT
)
if (mbap
->mi_driver
== 0)
register struct uba_device
*ubap
;
for (ubap
= ubdinit
; ubap
->ui_driver
; ubap
++)
if (ubap
->ui_alive
&& ubap
->ui_slave
== unit
&&
ubap
->ui_ctlr
== controller
&&
ubap
->ui_ubanum
== adaptor
&&
ubap
->ui_driver
->ud_dname
[0] == devname
[majdev
][0] &&
ubap
->ui_driver
->ud_dname
[1] == devname
[majdev
][1])
if (ubap
->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
;