📄 sd.c
字号:
/* * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * OMRON Corporation. * * 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. * * @(#)sd.c 8.3 (Berkeley) 12/7/93 *//* * sd.c -- SCSI Disk Device Driver * remaked by A.Fujita, MAR-22-1992 *//* * SCSI CCS (Command Command Set) disk driver. */#include "sd.h"#if NSD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <sys/dkstat.h>#include <sys/proc.h>#include <sys/disklabel.h>#include <luna68k/dev/device.h>#include <luna68k/dev/screg.h>#include <luna68k/dev/scvar.h>int sdinit(), sdstrategy(), sdstart(), sdintr();struct driver sddriver = { sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0};struct disklabel sdlabel[NSD];struct sd_softc { struct hp_device *sc_hd; struct scsi_queue sc_dq; short sc_flags; short sc_type; /* drive type */ short sc_punit; /* physical unit (scsi lun) */ u_int sc_blks; /* number of blocks on device */ int sc_blksize; /* device block size in bytes */ u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */} sd_softc[NSD];/* sc_flags values */#define SDF_ALIVE 0x1struct buf sdtab[NSD];struct scsi_fmt_sense sdsense[NSD];static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };#define sdunit(x) ((minor(x) >> 3) & 0x7)#define sdpart(x) (minor(x) & 0x7)#define sdpunit(x) ((x) & 7)#define sdminor(unit, part) (((unit) << 3) | (part))#define b_lba b_resid#define SDRETRY 3 /* IO retry count */struct sd_iostat { int imax; int imin; int omax; int omin;};struct sd_iostat sd_iostat[NSD] = { { 14000, -1, 100, -1 },};/* * Initialize */intsdinit(hd) register struct hp_device *hd;{ register struct sd_softc *sc = &sd_softc[hd->hp_unit]; register struct disklabel *lp; char *msg, *sdreadlabel(); sc->sc_hd = hd; sc->sc_punit = sdpunit(hd->hp_flags); sc->sc_type = sdident(sc, hd); if (sc->sc_type < 0) return(0); sc->sc_dq.dq_ctlr = hd->hp_ctlr; sc->sc_dq.dq_unit = hd->hp_unit; sc->sc_dq.dq_slave = hd->hp_slave; sc->sc_dq.dq_driver = &sddriver; /* * Use the default sizes until we've read the label, * or longer if there isn't one there. */ lp = &sdlabel[hd->hp_unit]; if (lp->d_secpercyl == 0) { lp->d_secsize = DEV_BSIZE; lp->d_nsectors = 32; lp->d_ntracks = 20; lp->d_secpercyl = 32*20; lp->d_npartitions = 1; lp->d_partitions[0].p_offset = 0; lp->d_partitions[0].p_size = LABELSECTOR + 1; } /* * read disklabel */ if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) { if (msg != NULL) { printf("sd%d: %s\n", hd->hp_unit, msg); return(0); } } sc->sc_flags = SDF_ALIVE; return(1);}static struct scsi_inquiry inqbuf;static struct scsi_fmt_cdb inq = { 6, CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0};static u_long capbuf[2];struct scsi_fmt_cdb cap = { 10, CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};intsdident(sc, hd) struct sd_softc *sc; struct hp_device *hd;{ char idstr[32]; int unit; register int ctlr, slave; register int i; register int tries = 10; ctlr = hd->hp_ctlr; slave = hd->hp_slave; unit = sc->sc_punit; /* * See if unit exists and is a disk then read block size & nblocks. */ while ((i = sc_test_unit_rdy(ctlr, slave, unit)) != 0) { if (i < 0 || --tries < 0) return (-1); if (i == STS_CHECKCOND) { u_char sensebuf[8]; struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; sc_request_sense(ctlr, slave, unit, sensebuf, 8); if (sp->class == 7 && sp->key == 6) /* drive doing an RTZ -- give it a while */ DELAY(1000000); } DELAY(1000); } if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, sizeof(inqbuf)) || scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, sizeof(capbuf))) /* doesn't exist or not a CCS device */ return (-1); switch (inqbuf.type) { case 0: /* disk */ case 4: /* WORM */ case 5: /* CD-ROM */ case 7: /* Magneto-optical */ break; default: /* not a disk */ return (-1); } sc->sc_blks = capbuf[0]; sc->sc_blksize = capbuf[1]; bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); for (i = 27; i > 23; --i) if (idstr[i] != ' ') break; idstr[i+1] = 0; for (i = 23; i > 7; --i) if (idstr[i] != ' ') break; idstr[i+1] = 0; for (i = 7; i >= 0; --i) if (idstr[i] != ' ') break; idstr[i+1] = 0; printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], &idstr[24]); printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); if (sc->sc_blksize != DEV_BSIZE) { printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE); return(1); } sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ return(inqbuf.type);}/* * Open */intsdopen(dev, flags, mode, p) dev_t dev; int flags, mode; struct proc *p;{ register int unit = sdunit(dev); register struct sd_softc *sc = &sd_softc[unit]; if (unit >= NSD) return(ENXIO); if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag)) return(ENXIO); if (sc->sc_hd->hp_dk >= 0) dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; return(0);}/* * Close */intsdclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p;{ return(0);}/* * Strategy */intsdstrategy(bp) register struct buf *bp;{ register int unit = sdunit(bp->b_dev); register int part = sdpart(bp->b_dev); register struct sd_softc *sc = &sd_softc[unit]; register struct disklabel *lp = &sdlabel[unit]; register struct partition *pp = &(lp->d_partitions[part]); register struct buf *dp = &sdtab[unit]; register daddr_t bn; register int sz, s; bn = bp->b_blkno; sz = howmany(bp->b_bcount, DEV_BSIZE); /* check that tracsfer is within a drive's partition */ if (bn < 0 || (bn + sz) > pp->p_size) { sz = pp->p_size - bn; if (sz == 0) { bp->b_resid = bp->b_bcount; goto done; } if (sz < 0) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; goto done; } bp->b_bcount = dbtob(sz); } /* calculate LBA for transfer */ bp->b_lba = bn + pp->p_offset; /* raise priority to block sdintr */ s = splbio(); /* call disksort to sort request into drive queue */ disksort(dp, bp); if (dp->b_active == 0) { /* */ dp->b_active = 1; sdustart(unit); } /* lower priority */ splx(s); return;done: biodone(bp);}intsdustart(unit) register int unit;{ register struct sd_softc *sc = &sd_softc[unit]; register struct hp_device *hp = sc->sc_hd; register struct scsi_queue *dq = &sc->sc_dq; register struct buf *bp = sdtab[unit].b_actf; register struct scsi_fmt_cdb *cmd; cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; *(int *)(&cmd->cdb[2]) = bp->b_lba; *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); dq->dq_cdb = cmd; dq->dq_bp = bp; dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ if (screq(dq)) sdstart(unit);}intsdstart(unit) register int unit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -