📄 sd.c
字号:
register struct sdst *st; register struct disklabel *dlp;{ register int i; dlp->d_type = DTYPE_SCSI; /* drive type */ dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */ dlp->d_nsectors = st->nsect; /* # sectors/track */ dlp->d_ntracks = st->ntrak; /* # tracks/cylinder */ dlp->d_ncylinders = st->ncyl; /* # cylinders */ dlp->d_secpercyl = st->nspc; /* # sectors/cylinder */ dlp->d_rpm = st->rps * 60; /* # revolutions / minute */ dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */ dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */ for (i = 0; i < PNUM; i++) { dlsz(i) = stsz(i); dlof(i) = stof(i); }}#undef stsz#undef stof#undef dlsz#undef dlof#undef disz#undef diofsd_calcpart(ii, disk_sizes, nsect, sectsize) register struct iop/**/_device *ii; register struct size disk_sizes[]; int nsect; int sectsize;{ register struct defpart *dp; register int size_mb; register int i; int psize; size_mb = nsect * sectsize / (1024 * 1024); for (dp = defpart_std; dp->range_max; dp++) if ((dp->range_min <= size_mb) && (size_mb < dp->range_max)) break; /* PASS1 */ for (i = 0; i < PNUM; i++) { psize = dp->partsize[i]; switch (psize) { case PART_UNUSED: disk_sizes[i].sd_nblocks = 0; break; case PART_SPEC: disk_sizes[i].sd_nblocks = nsect * sectsize / DEV_BSIZE; break; case PART_CALCF: case PART_CALCG: break; default: disk_sizes[i].sd_nblocks = psize; break; } } /* PASS2 */ for (i = 0; i < PNUM; i++) { psize = dp->partsize[i]; switch (psize) { case PART_UNUSED: case PART_SPEC: break; case PART_CALCF: disk_sizes[i].sd_nblocks = disk_sizes[PART_C].sd_nblocks - (disk_sizes[PART_A].sd_nblocks + disk_sizes[PART_B].sd_nblocks + disk_sizes[PART_D].sd_nblocks + disk_sizes[PART_E].sd_nblocks + disk_sizes[PART_H].sd_nblocks); break; case PART_CALCG: disk_sizes[i].sd_nblocks = disk_sizes[PART_C].sd_nblocks - (disk_sizes[PART_A].sd_nblocks + disk_sizes[PART_B].sd_nblocks + disk_sizes[PART_H].sd_nblocks); break; default: break; } } /* OFFSET */ disk_sizes[PART_A].sd_blkoff = 0; disk_sizes[PART_B].sd_blkoff = disk_sizes[PART_A].sd_nblocks; disk_sizes[PART_C].sd_blkoff = 0; disk_sizes[PART_D].sd_blkoff = disk_sizes[PART_A].sd_nblocks + disk_sizes[PART_B].sd_nblocks + disk_sizes[PART_H].sd_nblocks; disk_sizes[PART_E].sd_blkoff = disk_sizes[PART_D].sd_blkoff + disk_sizes[PART_D].sd_nblocks; disk_sizes[PART_F].sd_blkoff = disk_sizes[PART_E].sd_blkoff + disk_sizes[PART_E].sd_nblocks; disk_sizes[PART_G].sd_blkoff = disk_sizes[PART_D].sd_blkoff; if (disk_sizes[PART_H].sd_nblocks == 0) disk_sizes[PART_H].sd_blkoff = 0; else { disk_sizes[PART_H].sd_blkoff = disk_sizes[PART_A].sd_nblocks + disk_sizes[PART_B].sd_nblocks; } for (i = 0; i < PNUM; i++) if (disk_sizes[i].sd_nblocks == 0) disk_sizes[i].sd_blkoff = 0;}int sd_str_pr = 0;sdstrategy(bp) register struct buf *bp;{ register struct iop/**/_device *ii; register struct sdst *st; register struct buf *dp; register int unit; register int ssize; struct sdd_softc *sdd; struct sdc_softc *sdc; long bn; int xunit; int s; xunit = dev2part(bp->b_dev); unit = dev2unit(bp->b_dev); if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) goto bad; if (bp != &csdbuf[unit]) { /* * READ / WRITE command */ sdd = &sdd_softc[unit]; if (sdd->sdd_flags & SDDF_NONFMT) goto bad; sdc = &sdc_softc[ii->ii_ctlr]; ssize = sdd->sdd_sectsize; if ((ssize != DEV_BSIZE) && ((((dkblock(bp) * DEV_BSIZE) % ssize) != 0) || (((bp->b_flags & B_READ) == 0) && ((bp->b_bcount % ssize) != 0)))) { goto bad; } st = &sdstdrv[unit]; bn = dkblock(bp); bp->b_resid = 0; if ((bn < 0) || (bn >= st->sizes[xunit].sd_nblocks)) goto bad2; if (sd_access_check(bp) < 0) goto bad2;#ifdef notdef /* KU: XXX */ bp->b_cylin = (bn + st->sizes[xunit].sd_blkoff) / st->nspc; } else { bp->b_cylin = 0;#endif } s = splsc(); dp = &sdutab[ii->ii_unit]; disksort(dp, bp); if (dp->b_active == 0) { sdustart(ii); bp = &ii->ii_mi->im_tab; if (bp->b_actf && bp->b_active == 0) sdstart(ii->ii_mi); } splx(s); return;bad: bp->b_flags |= B_ERROR; goto done;bad2: bp->b_resid = bp->b_bcount;done: iodone(bp);}/* * Unit start routine. */sdustart(ii) register struct iop/**/_device *ii;{ register struct iop/**/_ctlr *im; register struct buf *dp; if (ii == NULL) return; im = ii->ii_mi; dk_busy &= ~(1 << ii->ii_dk); dp = &sdutab[ii->ii_unit]; if (dp->b_actf == NULL) return; /* * If the controller is active, just remember * that this device would like to be positioned ... * if we tried to position now we would confuse the SD. */ if (im->im_tab.b_active) { sdc_softc[im->im_ctlr].sdc_softas |= (1 << ii->ii_slave); return; } /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active == 0) dp->b_active = 1; /* * Device is ready to go * put it on the ready queue for the controller * (unless its already there.) */ if (dp->b_active != 2) { im->im_tab.b_actf = dp; dp->b_active = 2; }}/* * Start up a transfer on a drive. */sdstart(im) register struct iop/**/_ctlr *im;{ register struct buf *bp; register struct buf *dp; register struct sdc_softc *sdc;loop: /* * Pull a request off the controller queue. */ if ((dp = im->im_tab.b_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) return; /* * Mark controller busy, and * determine destination of this request. */ im->im_tab.b_active++; sdexec(bp);}voidsdexec(bp) register struct buf *bp;{ register struct iop/**/_device *ii; register struct buf_stat *bs; register struct scsi *sc; register int ssize; register int unit; register int intr; register int bn; struct sdc_softc *sdc; struct sdd_softc *sdd; struct sdst *st; int sz; int over; struct sc_map *map; unit = dev2unit(bp->b_dev); ii = sddinfo[unit]; intr = ii->ii_intr; sdd = &sdd_softc[unit]; sdc = &sdc_softc[ii->ii_ctlr]; sc = get_scsi(intr); if (bp == &csdbuf[unit]) { /* do sdcmd() */ bcopy((caddr_t)&kernscsi[unit], (caddr_t)sc, sizeof(struct scsi)); if (bp->b_un.b_addr == NULL) { map = 0; } else { map = get_sc_map(intr); sc->sc_map = (struct sc_map *)ipc_phys(map); } } else { /* R/W */ ssize = sdd->sdd_sectsize; st = &sdstdrv[unit]; bn = dkblock(bp); if (sdd->sdd_lastblk / st->nspc != bn / st->nspc) dk_seek[ii->ii_dk]++; st = &sdstdrv[unit]; bn = dkblock(bp); /* * Setup for the transfer, and get in the IOP queue. */ scinit(sc, ii->ii_slave, ssize); sc->sc_ctrnscnt = bp->b_bcount - bp->b_resid; map = get_sc_map(intr); sc->sc_map = (struct sc_map *)ipc_phys(map); /* cdb */ sc->sc_cdb.un_type1.t1_opcode = (bp->b_flags & B_READ) ? SCOP_EREAD : (ii->ii_flags & SD_F_WRTVRFY) ? SCOP_WRTVRFY : SCOP_EWRITE;#ifdef mips { int v; v = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) * DEV_BSIZE / sdd->sdd_sectsize; sc->sc_ladhi = v >> 16; sc->sc_ladlo = v; v = (sc->sc_ctrnscnt + ssize - 1) / ssize; sc->sc_cdb.un_type1.t1_p2 = v >> 8; sc->sc_cdb.un_type1.t1_p3 = v; }#else *(u_int *)(&sc->sc_cdb.un_type1.t1_ladhi) = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) * DEV_BSIZE / sdd->sdd_sectsize; *(u_short *)(&sc->sc_cdb.un_type1.t1_p2) = (sc->sc_ctrnscnt + ssize -1) / ssize;#endif if ((sdd->sdd_flags & SDDF_ERASEOFF) && ((bp->b_flags & B_READ) == 0)) { sc->sc_ctrl = 0x40; } } sdc->sdc_firmware |= SDCFW_BUSY; iop/**/go(ii, map);}/* * Now all ready to go. */sddgo(im) register struct iop/**/_ctlr *im;{ register int intr; im->im_tab.b_active = 2; intr = im->im_intr; sc_go(intr, get_scsi(intr), SCSI_INTEN);}/* * copyin(), copyout() can't use in the interrupt routine. * because user process is changed. *//* * Handle a disk interrupt. * d: controller number */sdintr(d) int d;{ register struct iop/**/_ctlr *im; register struct sdc_softc *sdc; register struct sdd_softc *sdd; register struct scsi *sc; register int intr; register int unit; register int slave; register int as; struct iop/**/_device *ii; struct sddevinfo *sdi; struct sc_extnd *sce; struct sdst *st; struct buf *bp; struct buf *dp; char *erp_page; int code; int len; int tstatus; int delay_start(); int delay_medrmv(); int wait_re_init_done(); im = sdminfo[d]; sdc = &sdc_softc[im->im_ctlr]; intr = im->im_intr; as = sdc->sdc_softas; sdc->sdc_wticks = 0; sc = get_scsi(intr); /* * If SDCS_IOCTL bit is set, then don't check error. */ if (sdc->sdc_state & SDCS_IOCTL) { sdc->sdc_state &= ~SDCS_IOCTL; sdd = &sdd_softc[(sdip[d][sc->sc_identify & IDT_DRMASK])->ii_unit]; if (sdc->sdc_state & SDCS_SCUNLOCK) { int s; sdc->sdc_state &= ~SDCS_SCUNLOCK; s = splclock(); if (sdc->sdc_state & SDCS_OPEN_WAIT) { sdc->sdc_state &= ~SDCS_OPEN_WAIT; wakeup((caddr_t)sdc); } splx(s); /* * UNLOCK SCSI access */ sdc->sdc_firmware &= ~SDCFW_BUSY; } return; } im->im_tab.b_active = 1; /* * Get device and block structures, and a pointer * to the iop_device for the drive. */ dp = im->im_tab.b_actf; bp = dp->b_actf; unit = dev2unit(bp->b_dev); ii = sddinfo[unit]; slave = ii->ii_slave; st = &sdstdrv[unit]; dk_busy &= ~(1 << ii->ii_dk); sdd = &sdd_softc[unit]; sdi = &sddevinfo[ii->ii_type]; sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; /* * Check error on the drive. */ tstatus = sc->sc_tstatus & TGSTMASK; if (sc->sc_istatus != INST_EP) { /* * initiator status is bad. * check & retry !! */ if ((sc->sc_istatus&(INST_EP|INST_PRE)) == (INST_EP|INST_PRE)) { /* detect parity error or abnormal terminate */ if ((sc->sc_istatus & INST_LB) == 0) printf("sd%d: SCSI bus parity error\n", unit); sdc->sdc_countcc--; goto sdintr_exec; } if ((sc->sc_istatus & INST_EP) == 0) { if (sc->sc_istatus & (INST_WAIT | INST_IP | INST_WR)) { if (++sdc->sdc_retrycnt < NRETRY) { im->im_tab.b_active = 2; /* * Konomama return sitemo, * lost interrupt ni narudake deha * naidarou ka ? * Isso error ni sitahou ga * ii nodeha naidarou ka ? */ return; } } printf("SCSI%d: abnormal termination\n", intr); printf("ISTAT = 0x%x, TSTAT = 0x%x\n", sc->sc_istatus, sc->sc_tstatus); if (++sdc->sdc_nhrderr >= MAXHRDERR) { printf("SCSI%d: too many hard errors\n", intr); sdc->sdc_nhrderr = 0; goto sdintr_error; } screset(intr); goto sdintr_exec; } if ((sc->sc_istatus & (INST_TO|INST_HE)) != 0) { if (sc->sc_istatus & INST_HE) { /* * SCSI bus reset is occured. * to be continue --> hdreset() */ re_init_done = 0; timeout(wait_re_init_done, bp, 10*hz); return; } if (++sdc->sdc_nhrderr >= MAXHRDERR) { printf("SCSI%d: too many hard errors (ISTAT=0x%x)\n", intr, sc->sc_istatus); sdc->sdc_nhrderr = 0; goto sdintr_error; } if (++sdc->sdc_retrycnt >= NRETRY) { printf("SCSI%d: too many initiator errors (ISTAT=0x%x)\n", intr, sc->sc_istatus); goto sdintr_error; } DELAY(D100MSEC * 10); goto sdintr_exec; } } if (sdd->sdd_flags & SDDF_SKIPCHECK) goto sdintr_done;check_target_status: /* * check target status */ switch (sdc->sdc_state) { /********************************/ /* */ /* NORMAL OPERATION */ /* */ /********************************/ case SDCS_NORMAL: switch (tstatus) { case TGST_GOOD: break; case TGST_CC: sdc->sdc_state |= SDCS_RSENSE;sdintr_rsense: im->im_tab.b_active = 2; bzero((caddr_t)sce, RSEN_CNT); scop_rsense(intr, sc, slave, SCSI_INTEN, RSEN_CNT, (caddr_t)sce); return; case TGST_BUSY: if (++sdc->sdc_retrycnt > MAXRETRYCNT) { goto sdintr_error; } timeout(sdexec, (caddr_t)bp, hz); return; default: printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -