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

📄 simdisk.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lintstatic        char sccsid[] = "@(#)simdisk.c 1.1 92/07/30";#endif/* * Copyright (c) 1987 by Sun Microsystems, Inc. *//* * Dummy driver for sparc simulated disks. *	uses systems calls via simulator to accomplish *	base level open, seek, read, and write operations */int errno;#include <sys/param.h>#include <sys/systm.h>#include <sys/dk.h>#include <sys/buf.h>#include <sys/conf.h>#include <sys/dir.h>#include <sys/user.h>#include <sys/map.h>#include <sys/vmmac.h>#include <sys/ioctl.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/dkbad.h>#include <sys/file.h>#include <machine/pte.h>#include <machine/psl.h>#include <machine/mmu.h>#include <machine/cpu.h>#include <vm/page.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <sundev/mbvar.h>#include <sas_simdef.h>	/* Defintions for real devices used by simulator */#ifdef IOMMU#include <machine/iommu.h>#endif IOMMUint	nsimd = 0;int	simdidentify();int	simdattach();int	simdintr();int	simdstart();#define	SIMDISK_OK	0#define	SIMDISK_RD	1#define	SIMDISK_WR	2#define	SIMDISK_ERR	3struct dev_ops simd_ops = {	1,	simdidentify,	simdattach};intsimdidentify(name)	char *name;{#if defined(SIMD_DEBUG)	printf("simdidentify: <%s> ", name);#endif	if (strcmp(name, "simd")) {#if defined(SIMD_DEBUG)		printf("rejected\n\r", name);#endif		return 0;	}#if defined(SIMD_DEBUG)	printf("recognized\n\r");#endif	nsimd ++;	return 1;}union simcsr {	struct csr {		u_int	cnt	: 28; /* number of bytes to xfer/xferd */		u_int	cmd	:  2; /* read or write */		u_int	ie	:  1; /* interrupts enabled */		u_int	go	:  1; /* do the transfer */	}		s;	unsigned	w;};struct simdregs {	union simcsr	csr;	unsigned	saddr;	unsigned	part;	unsigned	block;};#define	NPARTS		8#define	UNIT(dev)	(((dev)&0x38) >> 3)#define	PART(dev)	((dev)&7)#define	DEV(u,p)	(((u)<<3)|(p))struct simdisk {	struct simdregs *regs;		/* mapped controller registers */	int		sizes[NPARTS];	/* partition sizes */	struct buf     *foq;		/* first on queue */	struct buf     *loq;		/* last on queue */	struct buf     *act;		/* current buf active */	unsigned	addr;		/* base of dvma region */	unsigned	offset;		/* total transferred so far */}      *simdunits = 0;intsimdattach(dev)	struct dev_info *dev;{	struct simdisk *sd;	static int unit = -1;	register int part;	int nreg, nint;	unit ++;#if defined(SIMD_DEBUG)	printf("simdidentify: attaching simd%d\n", unit);#endif	if (!simdunits) {		simdunits = (struct simdisk *)			new_kmem_zalloc((u_int)(nsimd * sizeof (struct simdisk)),					KMEM_SLEEP);		if (!simdunits) {			printf ("simd: no space for structures\n");			return -1;		}	}	dev->devi_unit = unit;	sd = simdunits + unit;	nreg = dev->devi_nreg;	if (nreg != 1) {		printf("simd: regs not specified correctly\n");		return -1;	}/* * assumption: if we have different "simd" nodes, then * they talk via different registers to the simulator, * and hence get different "spindles". */	sd->regs = (struct simdregs *)		map_regs(dev->devi_reg->reg_addr,			 dev->devi_reg->reg_size,			 dev->devi_reg->reg_bustype);	if (!sd->regs) {		printf("simd: unable to map registers\n");		return -1;	}	for (part=0; part<NPARTS; ++part) {		sd->regs->part = part;		sd->sizes[part] = sd->regs->block;#if defined(SIMD_DEBUG)		printf("simd%d: partition %d has %d blocks\n",		       unit, part, sd->sizes[part]);#endif	}	nint = dev->devi_nintr;	if (nint != 1) {		printf("simd: ints not specified correctly for unit %d\n",		       unit);		return -1;	}	addintr(dev->devi_intr->int_pri, simdintr, dev->devi_name, unit);	report_dev(dev);	return 0;}/*ARGSUSED*/simdopen(dev, flag)	register dev_t dev;	register int flag;{	register int unit = UNIT(dev);	register int part = PART(dev);	if (unit >= nsimd) {		printf("Illegal simulated disk unit (%d of %d).\n",		       unit, nsimd);		return (ENXIO);	}	if (part >= NPARTS) {		printf("Illegal simulated disk partition (%d of %d).\n",		       part, NPARTS);		return (ENXIO);	}	return 0;}simdsize(dev)	register dev_t dev;{	int	unit = UNIT(dev);	int	part = PART(dev);	int rv;	if (!simdunits) {#if defined(SIMD_DEBUG)		printf("simdsize: simdunits not allocated\n");#endif		return 0;	}	if (unit >= nsimd) {#if defined(SIMD_DEBUG)		printf("simdsize: bad unit (%d of %d)\n",		       unit, nsimd);#endif		return 0;	}	if (part >= NPARTS) {#if defined(SIMD_DEBUG)		printf("simdsize: bad part (%d of %d)\n",		       part, NPARTS);#endif		return 0;	}	rv = simdunits[unit].sizes[part];#if defined(SIMD_DEBUG)	printf("simdsize: simd%d%c has %d blocks\n",	       unit, part + 'a', rv);#endif	return rv;}simdstrategy(bp)	register struct buf *bp;{	register int    unit;		/* unit number */	register int    part;		/* partition number */	struct simdisk *sd;	int             s;		/* psr bits for splx */	unit = UNIT(bp->b_dev);	part = PART(bp->b_dev);	sd = simdunits + unit;	if (bp->b_bcount & (DEV_BSIZE - 1)) {		printf("simd%d%c: non-block size i/o request\n", unit, part+'a');		goto bad;	}	s = splhigh();		/* protect from simdintr */	if (!sd->foq) {		sd->foq = bp;	} else {		sd->loq->av_forw = bp;	}	bp->av_forw = NULL;	sd->loq = bp;	simdstart(sd);	splx(s);		/* end of critical section */	return;bad:	bp->b_flags |= B_ERROR;	iodone(bp);	return;}/* * simdstart: start a transfer. * must be at a high enough priority * that the sd->foq/sd->eoq structure * is protected from simdintr(). * called from simdintr() and * from simdstrategy(). */simdstart(sd)	register struct simdisk *sd;{	register struct buf *bp;	/* buf we want to transfer */	register u_int  addr;		/* dvma cookie */	for (bp = sd->foq; bp && !sd->act; bp = bp->av_forw) {		addr = mb_mapalloc(dvmamap, bp, SBUS_MAP,				   simdstart, (caddr_t)sd);		if (!addr)			break;		bp->b_resid = bp->b_bcount;		sd->act = bp;		sd->addr = addr;		sd->offset = 0;		simdgo(sd);	}	sd->foq = bp;	return 0;}/* * simdgo: sd->{act,addr,offset} refer to a transfer that needs * to be started. inform the simulator. */simdgo(sd)	struct simdisk *sd;{	int unit;	int part;	struct buf     *bp;	unsigned        addr;	union simcsr    t;	unsigned        block;	unsigned        count;	bp = sd->act;	if (!bp)		return;	addr = sd->addr + sd->offset + (u_int) DVMA;	unit = minor(bp->b_dev);	block = dkblock(bp) + (sd->offset >> DEV_BSHIFT);	count = bp->b_resid - sd->offset;	/* don't transfer across pages, thanks. */	if (((addr & MMU_PAGEOFFSET) + count) > MMU_PAGESIZE)		count = MMU_PAGESIZE - (addr & MMU_PAGEOFFSET);	t.w = 0;	t.s.ie = 1;	t.s.cnt = count;	if (bp->b_flags & B_READ)		t.s.cmd = SIMDISK_RD;	else		t.s.cmd = SIMDISK_WR;	t.s.go = 1;	sd->regs->part = unit;	sd->regs->block = block;	sd->regs->saddr = addr;	sd->regs->csr = t;}/* * simdintr: a transfer completed. * update the sd->* variables; if * there is more to do, poke simdgo(); * otherwise, tell the kernel the transfer * has completed, and poke simdstart() to * get the next buffer on the list. */simdintr(){	int             unit;	struct simdisk *sd;	struct buf     *bp;	union simcsr    csr;	int             count;	int rv;	rv = 0;	for (unit=0; unit<nsimd; ++unit) {		sd = simdunits + unit;		bp = sd->act;		if (!bp)			continue; /* nobody active */		csr = sd->regs->csr;		if (csr.s.go)			continue; /* still busy */		if (csr.s.cmd == SIMDISK_ERR)			bp->b_flags |= B_ERROR;		count = csr.s.cnt;		sd->offset += count;		if ((sd->offset >= bp->b_bcount) ||		    (bp->b_flags & B_ERROR)) {			bp->b_resid = bp->b_bcount - sd->offset;			mb_mapfree(dvmamap, &sd->addr);			sd->act = 0;			iodone(bp);			simdstart(sd); /* do another */		} else			simdgo(sd); /* continue */		rv = 1;	}	return rv;}simdcheck(){	if (nsimd > 0)		return;	panic("simd: missing devinfo node");}

⌨️ 快捷键说明

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