/* * This file contains *	1. oem modifiable configuration personality parameters *	2. oem modifiable system specific kernel personality code */#include "sys/param.h"#include "sys/config.h"#include "sys/mmu.h"#include "sys/types.h"#include "sys/sysmacros.h"#include "sys/systm.h"#include "sys/map.h"#include "sys/dir.h"#include "sys/signal.h"#include "sys/user.h"#include "sys/errno.h"#include "sys/proc.h"#include "sys/buf.h"#include "sys/iobuf.h"#include "sys/reg.h"#include "sys/file.h"#include "sys/inode.h"#include "sys/seg.h"#include "sys/acct.h"#include "sys/sysinfo.h"#include "sys/var.h"#include "sys/ipc.h"#include "sys/shm.h"#include "sys/termio.h"#include "sys/conf.h"#include "sys/cops.h"#include "sys/pport.h"#include "sys/local.h"#include "sys/l2.h"#include "sys/kb.h"#include "sys/swapsz.h"/*char oemmsg[] =	"UniSoft Systems distribution system release 1.5";*/char oemmsg[] =	"UniSoft Systems pre-distribution system (release 1.5+)";int	sspeed = B9600;		/* default console speed */int	parityno = 28;		/* parity interrupt vector */int	cmask = CMASK;		/* default file creation mask */int	cdlimit = CDLIMIT;	/* default file size limit */char	slot[NSLOTS];		/* card ID numbers for expansion cards *//* * Kernel initialization functions. * Called from main.c while at spl7 in the kernel. */oem7init()	/* alias (formerly) "lisainit" */{#ifdef SUNIX	int dev;	extern dev_t swapdev;	extern int nswap;#endif SUNIX	extern struct rtime rtime;	extern int pmvect[];	extern int tevect[];	register short *sidp;		/* slot ID pointer */	register slotid, i;	register long *ip;	l2init();			/* setup the COPS ports */	/* This mess disables the verticle retrace interrupt, for now.	 */	do {		VRON = 1;	} while ((STATUS & S_VR) != 0);	do {		VROFF = 1;	} while ((STATUS & S_VR) == 0);	/* Some of the initialization requires that interrupts be enabled to	 * pick up coded sequences from the keyboard cops.  If interrupts were	 * masked out then the time returned by READCLOCK would fill the	 * buffer and KBENABLE, which also returns a value, would have trouble.	 */	SPL1();				/* ok, do it to me */	l2copscmd(MOUSEOFF);		/* shut off mouse interrupts */	l2copscmd(READCLOCK);		/* get time of day */	l2copscmd(KBENABLE);		/* enable keyboard */	sninit();			/* Sony initialization */	/* Wait 'til the clock data (from READCLOCK) and keyboard ID (from 	   KBENABLE) have come in, and the keyboard is back in NORMALWAIT */	while (kb_state);	time = rtime.rt_tod;	SPL7();				/* it should be at level 7 for the rest (?) */	/* Find out what's in each of the expansion slots.	 */	for (i = 0, sidp = SLOTIDS; i < NSLOTS; i++, sidp++) {		slot[i] = 0xFF;			/* not supported */		slotid = *sidp & SLOTMASK;		if (!slotid) {			if (iocheck((caddr_t)(STDIO+i*0x4000+1))) {				printf("Expansion slot %d: quad serial card\n",					i+1);				if (teinit(i) == 0) {					/*					 * point to interrupt vector,					 * set tecmar quad serial board inter loc,					 * and initialize hdwr					 */					ip = &((long *) 0)[EXPIVECT+devtoslot(i)];					*ip = (long)tevect + (long)(devtoslot(i)<<2);				}			}			continue;		}		printf("Expansion slot %d: ", i+1);		switch (slotid) {		case ID_APLNET:			printf("applenet card\n");			break;		case ID_PRO:			printf("ProFile card\n");			break;		case ID_2PORT:			printf("two port card\n");			slot[i] = PR0;		/* valid */			break;		case ID_PRIAM:			printf("Priam card\n");			ip = &((long *) 0)[EXPIVECT+devtoslot(i)];	/* point to int vector */			*ip = (long)pmvect + (long)(devtoslot(i)<<2);	/* set to Priam intr */			if (pmcinit(i) == 0)	/* initialize controller */				slot[i] = PM3;	/* valid */			break;		default:			printf("card ID 0x%x\n", slotid);		}	}	scinit();			/* SCC serial initialization */#ifdef UCB_NET	netinit();#endif	/* Now enable the verticle retrace interrupt, used for the system clock.	 */	do {		VRON = 1;	} while ((STATUS & S_VR) != 0);#ifdef SUNIX	SPL0();	/* This is the first unix booted during installation so find swapdev. */	if (rootdev == makedev(SN1, 0)) {		while (chkdev(dev = getdevnam()))			printf("Unable to use that device\nTry again:\n");		printf("\n\nswapdev = 0x%x\n\n", dev);		swapdev = dev;		if (major(dev) == PR0) nswap = PRNSWAP;		else if (major(dev) == PM3) nswap = PMNSWAP;		else if (major(dev) == CV2) nswap = CVNSWAP;		else panic("cannot determine size of swapdev");	}#endif SUNIX}/* * Kernel initialization functions. * Called from main.c while at spl0 in the kernel. */oem0init(){}/* * parityerror() *	Called from trap for parity error traps via *	interrupt level "parityno" (conf.c). *	Should return non-zero for fatal errors. *	Should return zero for a transient warning error. */parityerror(){	printf("parity error\n");	return(-1);}/* * reboot the system * called from reboot function */doboot(){	kb_state = SHUTDOWN;	/* SHUTDOWN (see kb.c)*/	SPL7();			/* extreme priority */	rom_mon();		/* return to the ROM monitor */	/*NOTREACHED*/}/* * OEM supplied subroutine called on process exit *//* ARGSUSED */oemexit(p)register struct proc *p;{#ifdef lint	/* for lint use p */	p->p_flag++;#endif}struct device_d *pro_da[NPPDEVS] = {		/* DEV	Description */	PPADDR,					/* 0x00	parallel port */	(struct device_d *)(STDIO+0x2000),	/* 0x10	FPC port 0 slot 1 */	(struct device_d *)(STDIO+0x2800),	/* 0x20	FPC port 1 slot 1 */	(struct device_d *)(STDIO+0x3000),	/* 0x30	FPC port 2 slot 1 !!!*/	(struct device_d *)(STDIO+0x6000),	/* 0x40	FPC port 0 slot 2 */	(struct device_d *)(STDIO+0x6800),	/* 0x50	FPC port 1 slot 2 */	(struct device_d *)(STDIO+0x7000),	/* 0x60	FPC port 2 slot 2 !!!*/	(struct device_d *)(STDIO+0xA000), 	/* 0x70	FPC port 0 slot 3 */	(struct device_d *)(STDIO+0xA800),	/* 0x80	FPC port 1 slot 3 */	(struct device_d *)(STDIO+0xB000)	/* 0x90	FPC port 2 slot 3 !!!*/};int (*pi_fnc[NPPDEVS])();	/* slots for interrupt handler addresses *//* Set the interrupt handler for a given parallel port controller. */setppint(addr, fnc)struct device_d *addr;int (*fnc)();{	register int i;	extern int cvint(), prointr(), lpintr();	for (i=0; i<NPPDEVS; i++)		if (pro_da[i] == addr) {	/* found dev number */			if (pi_fnc[i]) {	/* in use */				if (pi_fnc[i] == fnc) /* same handler */					return 0;     				if (pi_fnc[i] == prointr)					printf("ALREADY assigned to profile\n");				else if (pi_fnc[i] == lpintr)					printf("ALREADY assigned to lp\n");				else if (pi_fnc[i] == cvint)					printf("ALREADY assigned to corvus\n");				else					printf("Assigned to unknown handler at 0x%x\n",pi_fnc[i]);				break;			}			pi_fnc[i] = fnc;			return 0;		}	return 1;}/* Free the interrupt handler slot for a given controller. */freeppin(addr)	struct device_d *addr;{	register int i;	for (i=0; i<NPPDEVS; i++)		if (pro_da[i] == addr) {			pi_fnc[i] = 0;			return;		}}/* * ppintr - handle interrupt from parallel port controllers */ppintr(ap)struct args *ap;{	register int i, j;	register char a;	register struct device_d *dp;	int (*fnc)(), ebintr(), prointr(), cvint(), lpintr();	extern char lpflg[];	if((i = ap->a_dev) == 0) {		/* special case for pp 0 */		if(fnc = pi_fnc[i]) {			fnc(i);			return;		}	}	j = i + 2;	while (i < j) {		dp = pro_da[i];		if ((a = dp->d_ifr) & FCA1) {			asm("	nop ");			dp->d_ifr = a;	/* reset interrupt */			if (fnc = pi_fnc[i]) {				if (fnc == lpintr)					lpflg[i] = 0;				else if (fnc != ebintr &&					fnc != prointr &&					fnc != cvint) {					printf("pi_fnc[%d] = 0x%x invalid!!\n",						i,fnc);					return;				}				fnc(i);				return;			}#ifdef INTDUMP			ppdump(i,dp);#endif INTDUMP			return;		}		i++;	}}#ifdef INTDUMPppdump(n, p)register struct device_d *p;{	printf("pport %d: ",n);	printf("ifr=%x acr=%x pcr=%x ddra=%x ddrb=%x irb=%x\n",		p->d_ifr&0xFF, p->d_acr&0xFF, p->d_pcr&0xFF, p->d_ddra&0xFF,		p->d_ddrb&0xFF, p->d_irb&0xFF);}#endif INTDUMP/* *	called from clock if there's a panic in progress */clkstop(){	VROFF = 1;		/* disable vertical retrace intr */}nmikey(){	int i;	register short status;	/* added 7/25/84 to provide more info than "NMI key".	 * (taken from section 2.8 of Lisa Theory of Operations)	 */	printf("non-maskable interrupt: ");	status = STATUS;	if (status & S_SMEMERR)		printf("soft memory error\n");	else if (status & S_HMEMERR)		printf("hard memory error\n");	else		printf("power failure/keyboard reset\n");#ifdef HOWFAR	showbus();#endif HOWFAR	for (i=0xC00000; i>0; i--) ;	/* delay */}#ifdef SUNIX/* Get swap device name */getdevnam (){	char *p, *gets();	int unit, dev;retry:	printf("\n\nWhere is the swap area?\n");	printf("Enter:  'p' for builtin disk or a profile disk\n");	printf("        'c' for Corvus disk\n");	printf("        'pm' for Priam disk\n");	p = gets();	switch (p[0]) {	case 'p':		dev = PR0;		if (p[1] == 'm')			dev = PM3;		break;	case 'c':		dev = CV2;		break;	default:		printf("Invalid input. Try again.\n");		goto retry;	}	printf("Where will the disk be?\n");	if ((dev == PR0) || (dev == CV2)) {		printf("Enter:  '0' for builtin port\n");		printf("        '1' for Expansion Slot 1, Bottom Port\n");		printf("        '2' for Expansion Slot 1, Top Port\n");		printf("        '4' for Expansion Slot 2, Bottom Port\n");		printf("        '5' for Expansion Slot 2, Top Port\n");		printf("        '7' for Expansion Slot 3, Bottom Port\n");		printf("        '8' for Expansion Slot 3, Top Port\n");		p = gets();		switch (p[0]) {		case '0':		case '1':		case '2':		case '4':		case '5':		case '7':		case '8':			unit = p[0] - '0';			break;		default:			printf("Invalid input. Try again.\n");			goto retry;		}	} else { /* dev == PM3 */		printf("Enter:  '0' for Slot 1\n");		printf("        '1' for Slot 2\n");		printf("        '2' for Slot 3\n");		p = gets();		switch (p[0]) {		case '0':		case '1':		case '2':			unit = p[0] - '0';			break;		default:			printf("Invalid input. Try again.\n");			goto retry;		}	}	return makedev(dev, (unit<<4) | 1 );}chkdev(d){	return(*bdevsw[bmajor(d)].d_open)(minor(d), FREAD | FWRITE);}/* * This version of getchar reads directly from the keyboard in order to get * swapdev when the parallel port is not available.  It will not work once * the console has been formally opened. */char kb_getchr;cogetchar(){	SPL0();	while(kb_state) ;	/* wait for kb driver to finish special cmd */	kb_getchr = 1;		/* wait flag */	while (kb_getchr) ;	/* wait for it to happen */	return kb_chrbuf;}/* Kernel get string routine. * Useful for getting information from the console before the system * comes up.  The getchar routine will not work once the console has * been opened. */int (*getchar)() = cogetchar;extern int (*putchar)();char getsbuf[100];char *gets (){	register char *p;	register char c;	extern short kb_keycount;	p = getsbuf;	while (c = (*getchar)()) {		switch (c) {		case '\r':		case '\n':			goto out;		case '\b':			if (p > getsbuf) {				p--;			}			break;		case '@':		case 'X'&0x1F:		/* line kill */			if (p > getsbuf) {				p = getsbuf;				c = '\n';	/* echo a newline */			}			break;		default:			*p++ = c;		}		(*putchar)(c);		if (p >= getsbuf + sizeof(getsbuf)) {			printf("\nInput line too long, try again ...\n");			p = getsbuf;		}	}out:	*p = '\0';	(*putchar)('\n');	return getsbuf;}#endif SUNIX