⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdb.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)kdb.c	7.10 (Berkeley) 12/16/90 *//* * KDB50/MSCP device driver *//* * TODO *	rethink BI software interface *	write bad block forwarding code */#include "kra.h"		/* XXX */#define	DRIVENAMES	"kra"	/* XXX */#if NKDB > 0/* * CONFIGURATION OPTIONS.  The next three defines are tunable -- tune away! * * NRSPL2 and NCMDL2 control the number of response and command * packets respectively.  They may be any value from 0 to 7, though * setting them higher than 5 is unlikely to be of any value. * If you get warnings about your command ring being too small, * try increasing the values by one. * * MAXUNIT controls the maximum slave number (and hence number of drives * per controller) we are prepared to handle. */#define	NRSPL2	5		/* log2 number of response packets */#define NCMDL2	5		/* log2 number of command packets */#define	MAXUNIT	8		/* maximum allowed unit number */#include "sys/param.h"#include "sys/systm.h"#include "sys/malloc.h"#include "sys/map.h"#include "sys/buf.h"#include "sys/conf.h"#include "sys/user.h"#include "sys/proc.h"#include "sys/vm.h"#include "sys/dkstat.h"#include "sys/cmap.h"#include "sys/syslog.h"#include "sys/kernel.h"#define	NRSP	(1 << NRSPL2)#define	NCMD	(1 << NCMDL2)#include "../include/pte.h"#include "../include/cpu.h"#include "../vax/mscp.h"#include "../vax/mscpvar.h"#include "../include/mtpr.h"#include "bireg.h"#include "kdbreg.h"#include "../uba/ubavar.h"/* * Conversions from kernel virtual to physical and page table addresses. * PHYS works only for kernel text and primary (compile time) data addresses. */#define	PHYS(cast, addr) \	((cast) ((int)(addr) & 0x7fffffff))/* * KDB variables, per controller. */struct kdbinfo {	/* software info, per KDB */	struct	kdb_regs *ki_kdb;	/* KDB registers */	struct	kdb_regs *ki_physkdb;	/* phys address of KDB registers */	short	ki_state;		/* KDB50 state; see below */	short	ki_flags;		/* flags; see below */	int	ki_micro;		/* microcode revision */	short	ki_vec;			/* scb vector offset */	short	ki_wticks;		/* watchdog timer ticks */	/*	 * KDB PTEs must be contiguous.  Some I/O is done on addresses	 * for which this is true (PTEs in Sysmap and Usrptmap), but	 * other transfers may have PTEs that are scattered in physical	 * space.  Ki_map maps a physically contiguous PTE space used	 * for these transfers.	 */#define KI_MAPSIZ	(NCMD + 2)	struct	map *ki_map;		/* resource map */#define KI_PTES		256	struct	pte ki_pte[KI_PTES];	/* contiguous PTE space */	long	ki_ptephys;		/* phys address of &ki_pte[0] */	struct	mscp_info ki_mi;	/* MSCP info (per mscpvar.h) */	struct	buf ki_tab;		/* controller queue */	/* stuff read and written by hardware */	struct	kdbca ki_ca;		/* communications area */	struct	mscp ki_rsp[NRSP];	/* response packets */	struct	mscp ki_cmd[NCMD];	/* command packets */} kdbinfo[NKDB];#define	ki_ctlr	ki_mi.mi_ctlr/* * Controller states */#define	ST_IDLE		0	/* uninitialised */#define	ST_STEP1	1	/* in `STEP 1' */#define	ST_STEP2	2	/* in `STEP 2' */#define	ST_STEP3	3	/* in `STEP 3' */#define	ST_SETCHAR	4	/* in `Set Controller Characteristics' */#define	ST_RUN		5	/* up and running *//* * Flags */#define	KDB_ALIVE	0x01	/* this KDB50 exists */#define	KDB_GRIPED	0x04	/* griped about cmd ring too small */#define	KDB_INSLAVE	0x08	/* inside kdbslave() */#define	KDB_DOWAKE	0x10	/* wakeup when ctlr init done */struct kdbstats kdbstats;	/* statistics *//* * Device to unit number and partition: */#define	UNITSHIFT	3#define	UNITMASK	7#define	kdbunit(dev)	(minor(dev) >> UNITSHIFT)#define	kdbpart(dev)	(minor(dev) & UNITMASK)/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE *//* THESE SHOULD BE SHARED WITH uda.c (but not yet) */struct size {	daddr_t nblocks;	daddr_t blkoff;} kra81_sizes[8] = {#ifdef MARYLAND	67832,	0,		/* A=cyl    0 thru   94 + 2 sectors */	67828,	67832,		/* B=cyl   95 thru  189 - 2 sectors */	-1,	0,		/* C=cyl    0 thru 1247 */	-1,	135660,		/* D=cyl  190 thru 1247 */	449466,	49324,		/* E xxx */	64260,	498790,		/* F xxx */	328022,	563050,		/* G xxx */	0,	0,#else	15884,	0,		/* a */	33440,	15884,		/* b */	-1,	0,		/* c */	-1,	49324,		/* d */	449466,	49324,		/* e */	64260,	498790,		/* f */	328022,	563050,		/* g */	0,	0,#endif}, kra80_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	33440,	15884,		/* B=blk 15884 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	0,	0,	0,	0,	0,	0,	82080,	49324,		/* G=blk 49324 thru 131403 */	-1,	131404,		/* H=blk 131404 thru end */}, kra60_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	33440,	15884,		/* B=blk 15884 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	-1,	49324,		/* D=blk 49324 thru end */	0,	0,	0,	0,	82080,	49324,		/* G=blk 49324 thru 131403 */	-1,	131404,		/* H=blk 131404 thru end */};/* END OF STUFF WHICH SHOULD BE READ IN PER DISK *//* * Drive type index decoding table.  `ut_name' is null iff the * type is not known. */struct	kdbtypes {	char	*ut_name;	/* drive type name */	struct	size *ut_sizes;	/* partition tables */} kdbtypes[] = {	NULL,		NULL,	"ra80",		kra80_sizes,	/* 1 = ra80 */	NULL,		NULL,	NULL,		NULL,	"ra60",		kra60_sizes,	/* 4 = ra60 */	"ra81",		kra81_sizes,	/* 5 = ra81 */};#define NTYPES 6/* * Definition of the driver for autoconf and generic MSCP code. * SOME OF THIS IS BOGUS (must fix config) */#ifdef notdef		/* not when driver is for kra disks *//* * Some of these variables (per-drive stuff) are shared * with the UDA50 code (why not, they are the same drives). * N.B.: kdbdinfo must not be shared. */#define	kdbutab		udautab		/* shared */#define	kdbslavereply	udaslavereply	/* shared */#endifint	kdbprobe();		/* XXX */int	kdbslave(), kdbattach();int	kdbdgram(), kdbctlrdone(), kdbunconf(), kdbiodone();int	kdbonline(), kdbgotstatus(), kdbioerror();struct	uba_device *kdbdinfo[NKRA];	/* uba_device indeed! */struct	buf kdbutab[NKRA];	/* per drive transfer queue */u_short kdbstd[] = { 0 };	/* XXX */struct uba_driver kdbdriver =	/* XXX */ { kdbprobe, kdbslave, kdbattach, 0, kdbstd, DRIVENAMES, kdbdinfo, "kdb" };struct	mscp_driver kdbmscpdriver = { MAXUNIT, NKRA, UNITSHIFT, kdbutab, (struct disklabel *)0, kdbdinfo,   kdbdgram, kdbctlrdone, kdbunconf, kdbiodone,   kdbonline, kdbgotstatus, NULL, kdbioerror, NULL,   "kdb", DRIVENAMES };/* * Miscellaneous private variables. */char	kdbsr_bits[] = KDBSR_BITS;struct	uba_device *kdbip[NKDB][MAXUNIT];				/* inverting pointers: ctlr & unit => `Unibus'				   device pointer */daddr_t	ra_dsize[NKRA];		/* drive sizes, from on line end packets */struct	mscp kdbslavereply;	/* get unit status response packet, set				   for kdbslave by kdbunconf, via kdbintr */int	kdbwstart, kdbwatch();	/* watchdog timer */int	wakeup();/* * If kdbprobe is called, return 0 to keep Unibus code from attempting * to use this device.	XXX rethink *//* ARGSUSED */kdbprobe(reg, ctlr)	caddr_t reg;	int ctlr;{	return (0);}/* * Configure in a KDB50 controller. */kdbconfig(kdbnum, va, pa, vec)	int kdbnum;	struct biiregs *va, *pa;	int vec;{	register struct kdbinfo *ki;#define mi (&ki->ki_mi)#ifdef lint	extern int (*kdbint0[])();	(*kdbint0[0])(0);	/* this is a config botch */	kdbintr(0);#endif	/*	 * Set up local KDB status.	 */	ki = &kdbinfo[kdbnum];	ki->ki_kdb = (struct kdb_regs *)va;	ki->ki_physkdb = (struct kdb_regs *)pa;	ki->ki_vec = vec;	ki->ki_map =	    (struct map *)malloc((u_long)(KI_MAPSIZ * sizeof(struct map)),	    M_DEVBUF, M_NOWAIT);	if (ki->ki_map == NULL) {		printf("kdb%d: cannot get memory for ptes\n", kdbnum);		return;	}	ki->ki_ptephys = PHYS(long, ki->ki_pte); /* kvtophys(ki->ki_pte) */	ki->ki_flags = KDB_ALIVE;	/* THE FOLLOWING IS ONLY NEEDED TO CIRCUMVENT A BUG IN rminit */	bzero((caddr_t)ki->ki_map, KI_MAPSIZ * sizeof(struct map));	rminit(ki->ki_map, (long)KI_PTES, (long)1, "kdb", KI_MAPSIZ);	/*	 * Set up the generic MSCP structures.	 */	mi->mi_md = &kdbmscpdriver;	mi->mi_ctlr = kdbnum;	/* also sets ki->ki_ctlr */	mi->mi_tab = &ki->ki_tab;	mi->mi_ip = kdbip[kdbnum];	mi->mi_cmd.mri_size = NCMD;	mi->mi_cmd.mri_desc = ki->ki_ca.ca_cmddsc;	mi->mi_cmd.mri_ring = ki->ki_cmd;	mi->mi_rsp.mri_size = NRSP;	mi->mi_rsp.mri_desc = ki->ki_ca.ca_rspdsc;	mi->mi_rsp.mri_ring = ki->ki_rsp;	mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab;#undef mi}/* * Find a slave. * Note that by the time kdbslave is called, the interrupt vector * for the KDB50 has been set up (so that kdbunconf() will be called). */kdbslave(ui)	register struct uba_device *ui;{	register struct kdbinfo *ki;	register struct mscp *mp;	int next = 0, type, timeout, tries, i;#ifdef lint	i = 0; i = i;#endif	/*	 * Make sure the controller is fully initialised, by waiting	 * for it if necessary.	 */	ki = &kdbinfo[ui->ui_ctlr];	if (ki->ki_state == ST_RUN)		goto findunit;	tries = 0;again:	if (kdbinit(ki))		return (0);	timeout = todr() + 1000;		/* 10 seconds */	while (todr() < timeout)		if (ki->ki_state == ST_RUN)	/* made it */			goto findunit;	if (++tries < 2)		goto again;	printf("kdb%d: controller hung\n", ki->ki_ctlr);	return (0);	/*	 * The controller is all set; go find the unit.  Grab an	 * MSCP packet and send out a Get Unit Status command, with	 * the `next unit' modifier if we are looking for a generic	 * unit.  We set the `in slave' flag so that kdbunconf()	 * knows to copy the response to `kdbslavereply'.	 */findunit:	kdbslavereply.mscp_opcode = 0;	ki->ki_flags |= KDB_INSLAVE;	if ((mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT)) == NULL)		panic("kdbslave");		/* `cannot happen' */	mp->mscp_opcode = M_OP_GETUNITST;	if (ui->ui_slave == '?') {		mp->mscp_unit = next;		mp->mscp_modifier = M_GUM_NEXTUNIT;	} else {		mp->mscp_unit = ui->ui_slave;		mp->mscp_modifier = 0;	}	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;	i = ki->ki_kdb->kdb_ip;	/* initiate polling */	mp = &kdbslavereply;	timeout = todr() + 1000;	while (todr() < timeout)		if (mp->mscp_opcode)			goto gotit;	printf("kdb%d: no response to Get Unit Status request\n",		ki->ki_ctlr);	ki->ki_flags &= ~KDB_INSLAVE;	return (0);gotit:	ki->ki_flags &= ~KDB_INSLAVE;	/*	 * Got a slave response.  If the unit is there, use it.	 */	switch (mp->mscp_status & M_ST_MASK) {	case M_ST_SUCCESS:	/* worked */	case M_ST_AVAILABLE:	/* found another drive */		break;		/* use it */	case M_ST_OFFLINE:		/*		 * Figure out why it is off line.  It may be because		 * it is nonexistent, or because it is spun down, or		 * for some other reason.		 */		switch (mp->mscp_status & ~M_ST_MASK) {		case M_OFFLINE_UNKNOWN:			/*			 * No such drive, and there are none with			 * higher unit numbers either, if we are			 * using M_GUM_NEXTUNIT.			 */			return (0);		case M_OFFLINE_UNMOUNTED:			/*			 * The drive is not spun up.  Use it anyway.			 *			 * N.B.: this seems to be a common occurrance			 * after a power failure.  The first attempt			 * to bring it on line seems to spin it up			 * (and thus takes several minutes).  Perhaps			 * we should note here that the on-line may			 * take longer than usual.			 */			break;		default:			/*			 * In service, or something else equally unusable.			 */			printf("kdb%d: unit %d off line:", ki->ki_ctlr,				mp->mscp_unit);			mscp_printevent(mp);			goto try_another;		}		break;	default:		printf("kdb%d: unable to get unit status:", ki->ki_ctlr);		mscp_printevent(mp);		return (0);	}	/*	 * Does this ever happen?  What (if anything) does it mean?	 */	if (mp->mscp_unit < next) {		printf("kdb%d: unit %d, next %d\n",			ki->ki_ctlr, mp->mscp_unit, next);		return (0);	}	if (mp->mscp_unit >= MAXUNIT) {		printf("kdb%d: cannot handle unit number %d (max is %d)\n",			ki->ki_ctlr, mp->mscp_unit, MAXUNIT - 1);		return (0);	}	/*	 * See if we already handle this drive.	 * (Only likely if ui->ui_slave=='?'.)	 */	if (kdbip[ki->ki_ctlr][mp->mscp_unit] != NULL)		goto try_another;	/*	 * Make sure we know about this kind of drive.	 * Others say we should treat unknowns as RA81s; I am	 * not sure this is safe.	 */	type = mp->mscp_guse.guse_drivetype;	if (type >= NTYPES || kdbtypes[type].ut_name == 0) {		register long id = mp->mscp_guse.guse_mediaid;		printf("kdb%d: unit %d: media ID `", ki->ki_ctlr,			mp->mscp_unit);		printf("%c%c %c%c%c%d",			MSCP_MID_CHAR(4, id), MSCP_MID_CHAR(3, id),			MSCP_MID_CHAR(2, id), MSCP_MID_CHAR(1, id),			MSCP_MID_CHAR(0, id), MSCP_MID_NUM(id));		printf("' is of unknown type %d; ignored\n", type);try_another:		if (ui->ui_slave != '?')			return (0);		next = mp->mscp_unit + 1;		goto findunit;	}	/*	 * Voila!	 */	ui->ui_type = type;	ui->ui_flags = 0;	/* not on line, nor anything else */	ui->ui_slave = mp->mscp_unit;	return (1);}/* * Attach a found slave.  Make sure the watchdog timer is running. * If this disk is being profiled, fill in the `wpms' value (used by * what?).  Set up the inverting pointer, and attempt to bring the * drive on line. */kdbattach(ui)	register struct uba_device *ui;{	if (kdbwstart == 0) {		timeout(kdbwatch, (caddr_t)0, hz);		kdbwstart++;	}	if (ui->ui_dk >= 0)		dk_wpms[ui->ui_dk] = (60 * 31 * 256);	/* approx */	kdbip[ui->ui_ctlr][ui->ui_slave] = ui;	(void) kdb_bringonline(ui, 1);	/* should we get its status too? */}/* * Initialise a KDB50.  Return true iff something goes wrong. */kdbinit(ki)	register struct kdbinfo *ki;{	register struct kdb_regs *ka = ki->ki_kdb;	int timo;	/*	 * While we are thinking about it, reset the next command	 * and response indicies.	 */	ki->ki_mi.mi_cmd.mri_next = 0;	ki->ki_mi.mi_rsp.mri_next = 0;	/*	 * Start up the hardware initialisation sequence.	 */#define	STEP0MASK (KDB_ERR | KDB_STEP4 | KDB_STEP3 | KDB_STEP2 | KDB_STEP1)	ki->ki_state = ST_IDLE;	/* in case init fails */	bi_reset(&ka->kdb_bi);	/* reset bi node (but not the BI itself) */	timo = todr() + 1000;	while ((ka->kdb_sa & STEP0MASK) == 0) {		if (todr() > timo) {			printf("kdb%d: timeout during init\n", ki->ki_ctlr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -