/* autoconf.c 4.16 81/02/27 */
* Configure the system for the current machine.
int nexnum
; /* current nexus number */
int dkn
; /* number of dk numbers assigned so far */
int (*mbaintv
[4])() = { Xmba0int
, Xmba1int
, Xmba2int
, Xmba3int
};
int (*ubaintv
[4])() = { Xua0int
, Xua1int
, Xua2int
, Xua3int
};
(caddr_t
) 0x2013e000, (caddr_t
) 0x2017e000,
(caddr_t
) 0x201be000, (caddr_t
) 0x201fe000
struct percpu percpu
[] = {
#define NCPU (sizeof(percpu)/sizeof(struct percpu))
* 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
);
for (ocp
= percpu
; ocp
< &percpu
[NCPU
]; ocp
++)
if (ocp
->pc_cputype
== cpusid
.cpuany
.cp_type
) {
ip
= (int *)Sysmap
; *ip
&= ~PG_PROT
; *ip
|= PG_KR
;
printf("cpu type %d unsupported\n", cpusid
.cpuany
.cp_type
);
* Build configuration table for a 780, by looking
* at the things (mbas and ubas) in the nexus slots
* and initialzing each appropriately.
register struct percpu
*pcpu
;
register struct nexus
*nxv
;
register struct uba_hd
*uhp
;
struct nexus
*nxp
= NEX780
;
for (nexnum
= 0,nxv
= nexus
; nexnum
< NNEX780
; nexnum
++,nxp
++,nxv
++) {
nxaccess((caddr_t
)nxp
, Nexmap
[nexnum
]);
if (badaddr((caddr_t
)nxv
, 4))
if (nexcsr
.nex_csr
&NEX_APD
)
switch (nexcsr
.nex_type
) {
printf("mba%d at tr%d\n", nummba
, nexnum
);
printf("%d mba's not configured\n", nummba
+1);
printf("uba%d at tr%d\n", numuba
, nexnum
);
setscbnex(nexnum
, ubaintv
[numuba
]);
i
= nexcsr
.nex_type
- NEX_UBA0
;
unifind((struct uba_regs
*)nxv
, (struct uba_regs
*)nxp
,
((struct uba_regs
*)nxv
)->uba_cr
=
UBA_IFS
|UBA_BRIE
|UBA_USEFIE
|UBA_SUEFIE
;
/* there can be more than one... are there other codes??? */
printf("mcr%d at tr%d\n", nmcr
, nexnum
);
mcraddr
[nmcr
++] = (struct mcr
*)nxv
;
printf("nexus type %x", nexcsr
.nex_type
);
printf(" unsupported (at tr %d)\n", nexnum
);
timeout(ubawatch
, 0, HZ
);
* Configure a 750. There are four possible mba's,
* one standard UNIBUS, and a memory controller.
register struct nexus
*nxv
= nexus
;
struct nexus
*nxp
= NEX750
;
printf("mcr at %x\n", MCR_750
);
nxaccess((caddr_t
)MCR_750
, Nexmap
[nexnum
]);
mcraddr
[nmcr
++] = (struct mcr
*)nxv
;
for (nexnum
= 0; nexnum
< NNEX750
; nexnum
++, nxp
++, nxv
++) {
nxaccess((caddr_t
)nxp
, Nexmap
[nexnum
]);
if (badaddr((caddr_t
)nxv
, 4))
printf("mba%d at %x\n", nummba
, nxp
);
printf("%d mba's not configured\n", nummba
+1);
printf("uba at %x\n", nxp
);
nxaccess((caddr_t
)nxp
, Nexmap
[nexnum
++]);
unifind((struct uba_regs
*)nxv
++, (struct uba_regs
*)nxp
,
* 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
;
mdp
= (struct mba_regs
*)nxv
;
mba_hd
[nummba
].mh_mba
= mdp
;
mba_hd
[nummba
].mh_physmba
= (struct mba_regs
*)nxp
;
setscbnex(nexnum
, mbaintv
[nummba
]);
for (mbd
= mdp
->mba_drv
, dn
= 0; mbd
< &mdp
->mba_drv
[8]; mbd
++, dn
++) {
dt
= mbd
->mbd_dt
& 0xffff;
if ((dt
&MBDT_TYPE
) == MBDT_TU78
) {
printf("tm04/tu78 unsupported\n");
for (sn
= 0; sn
< 8; sn
++) {
if ((dt
& MBDT_SPR
) == 0)
mbaconfig(&fnd
, dt
&MBDT_TYPE
);
* Have found a massbus device;
* see if it is in the configuration table.
* If so, fill in its data.
register struct mba_info
*ni
;
register struct mba_info
*mi
;
register struct mba_hd
*mh
;
for (mi
= mbinit
; mi
->mi_driver
; mi
++) {
tp
= mi
->mi_driver
->md_type
;
for (mi
->mi_type
= 0; *tp
; tp
++, mi
->mi_type
++)
#define match(fld) (ni->fld == mi->fld || mi->fld == '?')
if (!match(mi_slave
) || !match(mi_drive
) || !match(mi_mbanum
))
printf("%c%d at mba%d drive %d\n",
mi
->mi_name
, 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_driver
->md_info
[mi
->mi_unit
] = mi
;
mi
->mi_mbanum
= ni
->mi_mbanum
;
mi
->mi_drive
= ni
->mi_drive
;
mi
->mi_slave
= ni
->mi_slave
;
if (mi
->mi_dk
&& dkn
< DK_NDRIVE
)
(*mi
->mi_driver
->md_dkinit
)(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_minfo
*um
;
register struct uba_dinfo
*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;
* 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.
unifind(vubp
, pubp
, vumem
, pumem
)
struct uba_regs
*vubp
, *pubp
;
register int br
, cvec
; /* MUST BE r11, r10 */
register struct uba_dinfo
*ui
;
register struct uba_minfo
*um
;
u_short
*umem
= (u_short
*)vumem
, *sp
, *reg
, addr
;
int i
, (**ivec
)(), haveubasr
= 0;
* Initialize the UNIBUS, by freeing the map
* registers and the buffered data path registers
uhp
->uh_map
= (struct map
*)calloc(UAMSIZ
* sizeof (struct map
));
mfree(uhp
->uh_map
, NUBMREG
, 1);
uhp
->uh_bdpfree
= (1<<NBDP780
) - 1;
uhp
->uh_bdpfree
= (1<<NBDP750
) - 1;
* Save virtual and physical addresses
* of adaptor, and allocate and initialize
* the UNIBUS interrupt vector.
uhp
->uh_vec
= (int(**)())calloc(512);
for (i
= 0; i
< 128; i
++)
scbentry(&catcher
[i
*2], SCB_ISTACK
);
nxaccess((struct nexus
*)pumem
, UMEMmap
[numuba
]);
vubp
->uba_sr
= vubp
->uba_sr
;
vubp
->uba_cr
= UBA_IFS
|UBA_BRIE
;
* 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 *)(&vubp
->uba_map
[0]) = UBA_MRV
;
#define ubaddr(off) (u_short *)((int)vumem + ((off)&0x1fff))
* 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
;
if (badaddr((caddr_t
)reg
, 2))
if (haveubasr
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
i
= (*udp
->ud_probe
)(reg
);
if (haveubasr
&& 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
);
um
->um_hd
= &uba_hd
[numuba
];
um
->um_addr
= (caddr_t
)reg
;
udp
->ud_minfo
[um
->um_ctlr
] = um
;
for (ivec
= um
->um_intr
; *ivec
; ivec
++) {
um
->um_hd
->uh_vec
[cvec
/4] =
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
!= '?')
if ((*udp
->ud_slave
)(ui
, reg
)) {
ui
->ui_ctlr
= um
->um_ctlr
;
ui
->ui_hd
= &uba_hd
[numuba
];
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= pumem
+ (addr
&0x1fff);
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
, 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
;
if (badaddr((caddr_t
)reg
, 2))
if (haveubasr
&& vubp
->uba_sr
) {
vubp
->uba_sr
= vubp
->uba_sr
;
i
= (*udp
->ud_probe
)(reg
);
if (haveubasr
&& 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
);
ui
->ui_hd
= &uba_hd
[numuba
];
for (ivec
= ui
->ui_intr
; *ivec
; ivec
++) {
ui
->ui_hd
->uh_vec
[cvec
/4] =
scbentry(*ivec
, SCB_ISTACK
);
ui
->ui_addr
= (caddr_t
)reg
;
ui
->ui_physaddr
= pumem
+ (addr
&0x1fff);
/* ui_type comes from driver */
udp
->ud_dinfo
[ui
->ui_unit
] = ui
;
register struct scb
*scbp
= &scb
;
scbp
->scb_ipl14
[nexnum
] = scbp
->scb_ipl15
[nexnum
] =
scbp
->scb_ipl16
[nexnum
] = scbp
->scb_ipl17
[nexnum
] =
scbentry(fn
, SCB_ISTACK
);
* Make a nexus accessible at physical address phys
* by mapping kernel ptes starting at pte.
* WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE
* SINCE MISSING NEXI DONT RESPOND. BUT THEN AGAIN
* PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE.
register struct pte
*pte
;
register int cnt
= btop(sizeof (struct nexus
));
register unsigned v
= btop(physa
);
*(int *)pte
++ = PG_V
|PG_KW
|v
++;