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

📄 fd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
 */Fdread(dev, uio)			/* character read routine */dev_t dev;struct uio *uio;{ 	int unit = FDUNIT(minor(dev)) ;	if (unit >= NFD) return(ENXIO);	return(physio(Fdstrategy,&fd_unit[unit].rhead,dev,B_READ,minphys,uio));}Fdwrite(dev, uio)			/* character write routine */dev_t dev;struct uio *uio;{ 	int unit = FDUNIT(minor(dev)) ;	if (unit >= NFD) return(ENXIO);	return(physio(Fdstrategy,&fd_unit[unit].rhead,dev,B_WRITE,minphys,uio));}/****************************************************************************//*                                 fdstart                                  *//****************************************************************************/fdstart(unit)int unit;{	register struct buf *dp,*bp;	int s;#ifdef FDTESTprintf("fd%d|",unit);#endif 	s = splbio();	if (!fd_unit[unit].motor) {		fd_turnon(unit);		/* Wait for 1 sec */		timeout(fdstart,unit,hz);		/*DELAY(1000000);*/	}else		 {		/* make sure drive is selected as well as on */		/*set_motor(unit,0);*/		dp = &fd_unit[unit].head;		bp = dp->b_actf;		fd_retry = 0;		if (fd_unit[unit].reset) fd_state = 1;		else {			/* DO a RESET */			fd_unit[unit].reset = 1;			fd_state = 5;		}		fd_skip = 0;#ifdef FDDEBUGprintf("Seek %d %d\n", bp->b_cylin, dp->b_step);#endif		if (bp->b_cylin != fd_track) {		/* Seek necessary, never quite sure where head is at! */		out_fdc(15);	/* Seek function */		out_fdc(unit);	/* Drive number */		out_fdc(bp->b_cylin * dp->b_step);		} else fdintr(0xff);	}	splx(s);}fd_timeout(x)int x;{	int i,j;	struct buf *dp,*bp;	dp = &fd_unit[fd_drive].head;	bp = dp->b_actf;	out_fdc(0x4);	out_fdc(fd_drive);	i = in_fdc();	printf("Timeout drive status %lx\n",i);	out_fdc(0x8);	i = in_fdc();	j = in_fdc();	printf("ST0 = %lx, PCN = %lx\n",i,j);	if (bp) badtrans(dp,bp);}/****************************************************************************//*                                 fdintr                                   *//****************************************************************************/fdintr(unit){	register struct buf *dp,*bp;	struct buf *dpother;	int read,head,trac,sec,i,s,sectrac,cyl;	unsigned long blknum;	struct fd_type *ft;#ifdef FDTEST	printf("state %d, unit %d, dr %d|",fd_state,unit,fd_drive);#endif	dp = &fd_unit[fd_drive].head;	bp = dp->b_actf;	read = bp->b_flags & B_READ; 	ft = &fd_types[FDTYPE(bp->b_dev)];	switch (fd_state) {	case 1 : /* SEEK DONE, START DMA */		/* Make sure seek really happened*/		if (unit != 0xff) {			out_fdc(0x8);			i = in_fdc();			cyl = in_fdc();			if (!(i&0x20) || (cyl != bp->b_cylin*dp->b_step)) {printf("Stray int ST0 = %lx, PCN = %lx:",i,cyl);				return;			}		}		fd_track = bp->b_cylin;		at_dma(read,bp->b_un.b_addr+fd_skip,FDBLK, fd_dmachan);		blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK			+ fd_skip/FDBLK;		sectrac = ft->sectrac;		sec = blknum %  (sectrac * 2);		head = sec / sectrac;		sec = sec % sectrac + 1;		if (read)  out_fdc(0xE6);	/* READ */		else out_fdc(0xC5);		/* WRITE */		out_fdc(head << 2 | fd_drive);	/* head & unit */		out_fdc(fd_track);		/* track */		out_fdc(head);		out_fdc(sec);			/* sector XXX +1? */		out_fdc(ft->secsize);		/* sector size */		out_fdc(sectrac);		/* sectors/track */		out_fdc(ft->gap);		/* gap size */		out_fdc(ft->datalen);		/* data length */		fd_state = 2;		/* XXX PARANOIA */		untimeout(fd_timeout,2);		timeout(fd_timeout,2,hz);		break;	case 2 : /* IO DONE, post-analyze */		untimeout(fd_timeout,2);		for(i=0;i<7;i++) {			fd_status[i] = in_fdc();		}		if (fd_status[0]&0xF8) {#ifdef FDOTHERprintf("status0 err %d:",fd_status[0]);#endif			goto retry;		}/*		if (fd_status[1]){			printf("status1 err %d:",fd_status[0]);			goto retry;		}		if (fd_status[2]){			printf("status2 err %d:",fd_status[0]);			goto retry;		}*/		/* All OK */		if (!kernel_space(bp->b_un.b_addr+fd_skip)) {			/* RAW transfer */			if (read) bcopy(dma_bounce[fd_dmachan]->b_un.b_addr,				bp->b_un.b_addr+fd_skip, FDBLK);		}		fd_skip += FDBLK;		if (fd_skip >= bp->b_bcount) {#ifdef FDTESTprintf("DONE %d|", bp->b_blkno);#endif			/* ALL DONE */			fd_skip = 0;			bp->b_resid = 0;			dp->b_actf = bp->av_forw;			biodone(bp);			nextstate(dp);		} else {#ifdef FDDEBUGprintf("next|");#endif			/* set up next transfer */			blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK				+ fd_skip/FDBLK;			fd_state = 1;			bp->b_cylin = (blknum / (ft->sectrac * 2));			if (bp->b_cylin != fd_track) {#ifdef FDTESTprintf("Seek|");#endif				/* SEEK Necessary */				out_fdc(15);	/* Seek function */				out_fdc(fd_drive);/* Drive number */				out_fdc(bp->b_cylin * dp->b_step);				break;			} else fdintr(0xff);		}		break;	case 3:#ifdef FDOTHERprintf("Seek %d %d\n", bp->b_cylin, dp->b_step);#endif		/* Seek necessary */		out_fdc(15);	/* Seek function */		out_fdc(fd_drive);/* Drive number */		out_fdc(bp->b_cylin * dp->b_step);		fd_state = 1;		break;	case 4:		out_fdc(3); /* specify command */		out_fdc(0xDF);		out_fdc(2);		out_fdc(7);	/* Recalibrate Function */		out_fdc(fd_drive);		fd_state = 3;		break;	case 5:#ifdef FDOTHER		printf("**RESET**\n");#endif		/* Try a reset, keep motor on */		set_motor(fd_drive,1);		set_motor(fd_drive,0);		outb(fdc+fdctl,ft->trans);		fd_retry++;		fd_state = 4;		break;	default:		printf("Unexpected FD int->");		out_fdc(0x8);		i = in_fdc();		sec = in_fdc();		printf("ST0 = %lx, PCN = %lx\n",i,sec);		out_fdc(0x4A); 		out_fdc(fd_drive);		for(i=0;i<7;i++) {			fd_status[i] = in_fdc();		}	printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",		fd_status[0], fd_status[1], fd_status[2], fd_status[3],		fd_status[4], fd_status[5], fd_status[6] );		break;	}	return;retry:	switch(fd_retry) {	case 0: case 1:	case 2: case 3:		break;	case 4:		fd_retry++;		fd_state = 5;		fdintr(0xff);		return;	case 5: case 6: case 7:		break;	default:		printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",		fd_status[0], fd_status[1], fd_status[2], fd_status[3],		fd_status[4], fd_status[5], fd_status[6] );		badtrans(dp,bp);		return;	}	fd_state = 1;	fd_retry++;	fdintr(0xff);}badtrans(dp,bp)struct buf *dp,*bp;{	bp->b_flags |= B_ERROR;	bp->b_error = EIO;	bp->b_resid = bp->b_bcount - fd_skip;	dp->b_actf = bp->av_forw;	fd_skip = 0;	biodone(bp);	nextstate(dp);}/*	nextstate : After a transfer is done, continue processing	requests on the current drive queue.  If empty, go to	the other drives queue.  If that is empty too, timeout	to turn off the current drive in 5 seconds, and go	to state 0 (not expecting any interrupts).*/nextstate(dp)struct buf *dp;{		if (dp->b_actf) 		fdstart(fd_drive);	else {#if NFD > 1		struct buf *dpother;		dpother = &fd_unit[fd_drive ? 0 : 1].head;		if (dpother->b_actf) {#ifdef FDTESTprintf("switch|");#endif			untimeout(fd_turnoff,fd_drive);			timeout(fd_turnoff,fd_drive,5*hz);			fd_drive = 1 - fd_drive;			dp->b_active = 0;			dpother->b_active = 1;			fdstart(fd_drive);		} else #endif		{#ifdef FDTESTprintf("off|");#endif			untimeout(fd_turnoff,fd_drive);			timeout(fd_turnoff,fd_drive,5*hz);			fd_state = 0;			dp->b_active = 0;		}	}}Fdioctl() {}Fddump() {}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -