📄 sd.c
字号:
} sdi = &sddevinfo[ii->ii_type]; } /* * Mode Select * Error Recovery Parameters set */ i = *(sdi->ERP_page +1) + 2; /* page length */ bzero(sdtmp, i + 4); bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i); scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_cpoint = sdtmp; uscsi.sc_ctrnscnt = i + 4; uscsi.sc_opcode = SCOP_MSELECT; uscsi.sc_lad = (SDM_PF << 16); uscsi.sc_count = i + 4; (void) sdcmd(dev, &uscsi); /* * Read Grown Defect list */ scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_cpoint = sdtmp; uscsi.sc_ctrnscnt = 4; uscsi.sc_opcode = SCOP_RDL; uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8; uscsi.sc_cdb.un_type1.t1_p3 = 4; (void) sdcmd(dev, &uscsi); i = *(short *)&sdtmp[2] / 8; if (i > (1024*9/10)) printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n", unit);mo_check_done: /* * Read Capacity */ bzero((caddr_t)sdtmp, 8); scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_cpoint = sdtmp; uscsi.sc_ctrnscnt = 8; uscsi.sc_opcode = SCOP_RCAP; (void) sdcmd(dev, &uscsi); sdd->sdd_nsect = *(int *)&sdtmp[0] + 1; sdd->sdd_sectsize = *(int *)&sdtmp[4]; if ((sdd->sdd_sectsize != DEV_BSIZE) && (sdd->sdd_sectsize != SDBSIZE1K)) sdd->sdd_sectsize = DEV_BSIZE; } if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE)) stat = EROFS;pre_open_done: if (stat == 0) { if ((isalone(unit) == ONLY_ONE) || media_changed) { /* * read partition information from sector zero. */ sdrpartinfo(ii); if (ii->ii_dk >= 0) { dk_wpms[ii->ii_dk] = sdd->sdd_sectsize * sdstdrv[unit].rps * sdstdrv[unit].nsect / (2 * 1000000); } } } else { /* * open error */ *sdopfp = old_sdopf; if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) { sdd->sdd_flags &= ~SDDF_INHRMV; scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_opcode = SCOP_MEDRMV; uscsi.sc_count = SDRMV_ALLOW; (void) sdcmd(dev, &uscsi); } } /* * UNLOCK open */ s = splclock(); sdd->sdd_flags &= ~SDDF_GETTMP; if (sdtmp_stat & B_WANTED) wakeup((caddr_t)sdtmp); sdtmp_stat &= ~(B_BUSY|B_WANTED); splx(s); return (stat);}int sd_access_check_on; /* Common flags for sd_access_check() */sd_access_check(bp) register struct buf *bp;{ register struct iop/**/_device *ii; register struct sdd_softc *sdd; int unit; int check_part; int limit; int over; register struct size *sizes; register int lba; /* logical block address */ register int sz; register int i; check_part = 0; unit = dev2unit(bp->b_dev); ii = sddinfo[unit]; sdd = &sdd_softc[unit]; sizes = sdstdrv[unit].sizes; lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp); sz = howmany(bp->b_bcount, sdd->sdd_sectsize); /* * When block device is used, * inhibit raw device write operation. */ if ((major(bp->b_dev) == sd_c_major) /* RAW I/O */ && ((bp->b_flags & B_READ) == 0) /* WRITE */ && ((ii->ii_flags & SD_F_ENW) == 0) /* INHIBIT */ && ((sd_access_check_on & SD_F_ENW) == 0)) { for (i = 0; i < PNUM; i++) { if (sd_b_openf[unit][i] == 0) continue; /* * |----|========|---|======|-------| * 1 |---+++--------------------------| CUT OFF * 2 |---++++++++++++-----------------| CUT OFF * 3 |---++++++++++++++++-------------| CUT OFF * 4 |---++++++++++++++++++++++++-----| CUT OFF * 5 |-------+++----------------------| ERROR * 6 |------------+++-----------------| ERROR * 7 |------------+++++++-------------| ERROR * 8 |------------+++++++++++++++-----| ERROR */ if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks)) && ((lba + sz) > sizes[i].sd_blkoff)) check_part |= (1 << i); } } if (check_part) { limit = 0x7fffffff; /* XXX */ for (i = 0; i < PNUM; i++) { if ((check_part & (1 << i)) == 0) continue; if (lba >= sizes[i].sd_blkoff) { bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid = bp->b_bcount; printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ", unit, pname[dev2part(bp->b_dev)]); printf("sn = 0x%x(%d), off = 0x%x(%d)\n", dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, sizes[dev2part(bp->b_dev)].sd_blkoff, sizes[dev2part(bp->b_dev)].sd_blkoff); return (-1); } if (sizes[i].sd_blkoff < limit) limit = sizes[i].sd_blkoff; } } else { limit = sizes[dev2part(bp->b_dev)].sd_blkoff + sizes[dev2part(bp->b_dev)].sd_nblocks; } if ((over = (lba + sz) - limit) > 0) { /* * Logical Block Address is outside the valid area. */ if (((ii->ii_flags & SD_F_EOLBA) != 0) || ((sd_access_check_on & SD_F_EOLBA) != 0)) { /* * error if outside LBA */ return(-1); } bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize; if (bp->b_resid >= bp->b_bcount) { bp->b_resid = bp->b_bcount; return(-1); } } return (0);}sd_b_close(dev, flag) dev_t dev; int flag;{ return (_sdclose(dev, flag, S_IFBLK));}sd_c_close(dev, flag) dev_t dev; int flag;{ return (_sdclose(dev, flag, S_IFCHR));}_sdclose(dev, flag, fmt) register dev_t dev; int flag; int fmt;{ register struct iop/**/_device *ii; register struct sdd_softc *sdd; register int unit; struct sdc_softc *sdc; struct scsi uscsi; struct sc_extnd *sce; unit = dev2unit(dev); if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) return (ENXIO); sdd = &sdd_softc[unit]; sdc = &sdc_softc[ii->ii_ctlr]; sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; /* * still remain jobs * sleep about 10ms -> 1sec */ while (ii->ii_mi->im_tab.b_actf != NULL) sleep((caddr_t)&lbolt, PRIBIO); if ((fmt & S_IFMT) == S_IFBLK) sd_b_openf[unit][dev2part(dev)] = 0; else sd_c_openf[unit][dev2part(dev)] = 0; sdd->sdd_flags &= ~SDDF_XUSE; if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) { sdd->sdd_flags &= ~SDDF_INHRMV; scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_opcode = SCOP_MEDRMV; uscsi.sc_count = SDRMV_ALLOW; (void) sdcmd(dev, &uscsi); } return (0);}sdcmd(dev, usc) dev_t dev; struct scsi *usc;{ register struct buf *bp; register struct scsi *ksc; register u_char *point; register int unit; int error; int s; int cnt; if (usc == 0) return (ENXIO); error = 0; unit = dev2unit(dev); bp = &csdbuf[unit]; /* * LOCK csdbuf */ s = splclock(); while (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } bzero((caddr_t)bp, sizeof(struct buf)); bp->b_flags = B_BUSY|B_READ; splx(s); ksc = &kernscsi[unit]; bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi)); /* * setup command buffer */ bp->b_dev = dev; bp->b_proc = curproc; cnt = ksc->sc_ctrnscnt; bp->b_bcount = cnt; point = ksc->sc_cpoint; bp->b_un.b_addr = (caddr_t)point; if (cnt > 0) { if (point == NULL) { ksc->sc_cpoint = point = get_scsi(unit)->sc_param; if (cnt > 20) { error = EFAULT; goto done; } } if (point < (u_char *)KERNBASE) { if (useracc(point, cnt, B_WRITE) == NULL) { error = EFAULT; goto done; } curproc->p_flag |= P_PHYSIO; vslock(point, cnt); bp->b_flags |= B_PHYS; }#ifndef mips else { if (kernacc(point, cnt, B_WRITE) == NULL) { error = EFAULT; goto done; } }#endif ksc->sc_tstatus = TS_MAPPED_PIO; /* XXX */ } /* * call strategy entry, and wait command done. */ sdstrategy(bp); iowait(bp); if ((cnt > 0) && (point < (u_char *)KERNBASE)) { vsunlock(point, cnt, B_READ); curproc->p_flag &= ~P_PHYSIO; } if ((bp->b_flags & B_ERROR) == 0) error = 0; else { if (bp->b_error) error = bp->b_error; else error = EIO; } bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi));done: /* * UNLOCK csdbuf */ s = splclock(); if (bp->b_flags & B_WANTED) wakeup((caddr_t)bp); bp->b_flags = 0; splx(s); return (error);}/* * read partition information from sector zero. */sdrpartinfo(ii) register struct iop/**/_device *ii;{ register struct disklabel *dlp; register struct sdst *hsp; register struct sdst *st; register int unit; register int i; struct firstsector *fsp; struct sdc_softc *sdc; struct sdd_softc *sdd; struct sddevinfo *sdi; struct scsi uscsi; int s; sdi = &sddevinfo[ii->ii_type]; unit = ii->ii_unit; sdd = &sdd_softc[unit]; sdc = &sdc_softc[ii->ii_ctlr]; if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) { register struct sc_rcap *scr = (struct sc_rcap *)sdtmp; sdd->sdd_flags |= SDDF_FMTDONE; bzero((caddr_t)sdtmp, 8); scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_cpoint = (u_char *)scr; uscsi.sc_ctrnscnt = 8; uscsi.sc_opcode = SCOP_RCAP; (void) sdcmd(unit << 3, &uscsi); sdd->sdd_nsect = scr->scr_nblock + 1; sdd->sdd_sectsize = scr->scr_blocklen; if (sdd->sdd_sectsize == 0) sdd->sdd_sectsize = SDBSIZE1K; } bzero(sdtmp, DEV_BSIZE); if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); uscsi.sc_cpoint = sdtmp; uscsi.sc_ctrnscnt = DEV_BSIZE; uscsi.sc_opcode = SCOP_READ; uscsi.sc_lad = 0; uscsi.sc_count = 1; (void) sdcmd(unit << 3, &uscsi); sdd->sdd_flags &= ~SDDF_SKIPCHECK; } fsp = (struct firstsector *)sdtmp; dlp = (struct disklabel *)(sdtmp + LABELOFFSET); s = splclock(); hsp = &sdstdrv[unit]; bzero((caddr_t)hsp, sizeof (struct sdst)); bzero(&sdlabel[unit], sizeof (struct disklabel)); if ((dlp->d_magic == DISKMAGIC) && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) { sdlabel[unit] = *dlp; disklabel2sdst(unit, dlp, hsp); } else { if ((ii->ii_type == UNKNOWN_DISK) || (sdi->sdstp->sizes == calc_disk_sizes)) { /* * If device is UNKNOWN PARTITION SIZE, * calculate default partition from capacity. */ st = sdi->sdstp; hsp->nsect = st->nsect; /* # sectors/track */ hsp->ntrak = st->ntrak; /* # tracks/cylinder */ hsp->nspc = st->nspc; /* # sectors/cylinder */ hsp->ncyl = st->ncyl; /* # cylinders */ hsp->rps = st->rps; /* # revolutions/sec */ hsp->sizes = sdsizedrv[unit]; /* partition table */ sd_calcpart(ii, hsp->sizes, sdd->sdd_nsect, sdd->sdd_sectsize); sdst2disklabel(unit, hsp, &sdlabel[unit]); } else { /* * If device is support disk, * copy default partition from size table. */ st = sdi->sdstp; hsp->nsect = st->nsect; /* # sectors/track */ hsp->ntrak = st->ntrak; /* # tracks/cylinder */ hsp->nspc = st->nspc; /* # sectors/cylinder */ hsp->ncyl = st->ncyl; /* # cylinders */ hsp->rps = st->rps; /* # revolutions / second */ hsp->sizes = sdsizedrv[unit]; /* partition table */ for (i = 0; i < PNUM; i++) { hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks; hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff; } sdst2disklabel(unit, hsp, &sdlabel[unit]); } } /* BEGIN XXX*/ if (hsp->rps == 0) { /* * If device is support disk, * copy default partition from size table. */ st = sdi->sdstp; hsp->nsect = st->nsect; /* # sectors/track */ hsp->ntrak = st->ntrak; /* # tracks/cylinder */ hsp->nspc = st->nspc; /* # sectors/cylinder */ hsp->ncyl = st->ncyl; /* # cylinders */ hsp->rps = st->rps; /* # revolutions / second */ sdst2disklabel(unit, hsp, &sdlabel[unit]); } /* END XXX*/ (void)splx(s);}static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n";static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n";#define stsz(N) st->sizes[(N)].sd_nblocks#define stof(N) st->sizes[(N)].sd_blkoff#define dlsz(N) dlp->d_partitions[(N)].p_size#define dlof(N) dlp->d_partitions[(N)].p_offset#define disz(N) dip->di_part[(N)].dp_nblocks#define diof(N) dip->di_part[(N)].dp_blkoff#ifndef BBSIZE#define BBSIZE 8192#endifstaticcheck_sdst(unit, st) int unit; struct sdst *st;{ if (st->nsect == 0) { st->nsect = 1; printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit); } if (st->rps == 0) { st->rps = 60; printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit); }}staticdisklabel2sdst(unit, dlp, st) int unit; register struct disklabel *dlp; register struct sdst *st;{ register int i; int msg_header_printed; msg_header_printed = 0; st->nsect = dlp->d_nsectors; /* # sectors/track */ st->ntrak = dlp->d_ntracks; /* # tracks/cylinder */ st->nspc = dlp->d_secpercyl; /* # sectors/cylinder */ st->ncyl = dlp->d_ncylinders; /* # cylinders */ st->rps = dlp->d_rpm / 60; /* # revolutions / second */ st->sizes = sdsizedrv[unit]; /* partition table */ check_sdst(unit, st); for (i = 0; i < PNUM; i++) { if (msg_header_printed == 0) { if (((stsz(i) != 0) || (stof(i) != 0)) && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) { msg_header_printed = 1; } } } for (i = 0; i < PNUM; i++) { stsz(i) = dlsz(i); stof(i) = dlof(i); } if (msg_header_printed) { printf(Warn_Part, unit); for (i = 0; i < PNUM; i++) printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i)); }}staticsdst2disklabel(unit, st, dlp) int unit; /*XXX*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -