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

📄 sd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -