📄 simdisk.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 + -