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

📄 wd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		 */		outb(wdc+wd_precomp, 0xff);/* sometimes this is head bit 3 */		outb(wdc+wd_seccnt, 1);		outb(wdc+wd_sector, LABELSECTOR+1);		/*if (bp->b_dev == bootdev) {			(wdc+wd_cyl_lo = cyloffset & 0xff;			(wdc+wd_cyl_hi = cyloffset >> 8;		} else {			(wdc+wd_cyl_lo = 0;			(wdc+wd_cyl_hi = 0;		}*/		outb(wdc+wd_cyl_lo, (cyloffset & 0xff));		outb(wdc+wd_cyl_hi, (cyloffset >> 8));		outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));		outb(wdc+wd_command, WDCC_READ);		du->dk_state = RDLABEL;		return(0);	case RDLABEL:		if ((stat = inb(wdc+wd_status)) & WDCS_ERR) {			if (++wdtab.b_errcnt < RETRIES)				goto retry;			printf("wd%d: read label", unit);			goto badopen;		}		insw(wdc+wd_data, bp->b_un.b_addr, 256);		if (((struct disklabel *)		    (bp->b_un.b_addr + LABELOFFSET))->d_magic == DISKMAGIC) {		       du->dk_dd =			 * (struct disklabel *) (bp->b_un.b_addr + LABELOFFSET);		} else {			printf("wd%d: bad disk label\n", du->dk_unit);			du->dk_state = OPENRAW;		}		s = splbio();		/* not called from intr level ... */		while ((stat = inb(wdc+wd_status)) & WDCS_BUSY);		wdsetctlr(bp->b_dev, du);		outb(wdc+wd_seccnt, 0);		splx(s);		if (du->dk_state == RDLABEL)			du->dk_state = RDBADTBL;		/*		 * The rest of the initialization can be done		 * by normal means.		 */		return(1);	default:		panic("wdcontrol");	}	/* NOTREACHED */badopen:	printf(": status %b error %b\n",		stat, WDCS_BITS, inb(wdc+wd_error), WDERR_BITS);	du->dk_state = OPENRAW;	return(1);}wdsetctlr(dev, du) dev_t dev; struct disk *du; {	int stat;	outb(wdc+wd_cyl_lo, du->dk_dd.d_ncylinders);	outb(wdc+wd_cyl_hi, (du->dk_dd.d_ncylinders)>>8);	outb(wdc+wd_sdh, WDSD_IBM | (wdunit(dev) << 4) + du->dk_dd.d_ntracks-1);	outb(wdc+wd_seccnt, du->dk_dd.d_nsectors);	outb(wdc+wd_command, 0x91);	while ((stat = inb(wdc+wd_status)) & WDCS_BUSY) ;	stat = inb(wdc+wd_error);	return(stat);}/* ARGSUSED */wdclose(dev, flags, fmt)        dev_t dev;        int flags, fmt;{	register struct disk *du;	du = &wddrives[wdunit(dev)];	du->dk_open-- ;	/*if (du->dk_open == 0) du->dk_state = CLOSED ; does not work */}wdioctl(dev,cmd,addr,flag)	dev_t dev;	caddr_t addr;{	int unit = wdunit(dev);	register struct disk *du;	int error = 0;	struct uio auio;	struct iovec aiov;	/*int wdformat();*/	du = &wddrives[unit];	switch (cmd) {	case DIOCGDINFO:		*(struct disklabel *)addr = du->dk_dd;		break;        case DIOCGPART:                ((struct partinfo *)addr)->disklab = &du->dk_dd;                ((struct partinfo *)addr)->part =                    &du->dk_dd.d_partitions[wdpart(dev)];                break;        case DIOCSDINFO:                if ((flag & FWRITE) == 0)                        error = EBADF;                else                        error = setdisklabel(&du->dk_dd,					(struct disklabel *)addr,                         0 /*(dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart*/);                /*if (error == 0 && dk->dk_state == OPENRAW &&                    vdreset_drive(vddinfo[unit]))                        dk->dk_state = OPEN;*/		wdsetctlr(dev, du);                break;        case DIOCWLABEL:                if ((flag & FWRITE) == 0)                        error = EBADF;                else                        du->dk_wlabel = *(int *)addr;                break;        case DIOCWDINFO:                if ((flag & FWRITE) == 0)                        error = EBADF;                else if ((error = setdisklabel(&du->dk_dd, (struct disklabel *)addr,                  0/*(dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart*/)) == 0) {                        int wlab;                        /*if (error == 0 && dk->dk_state == OPENRAW &&                            vdreset_drive(vddinfo[unit]))                                dk->dk_state = OPEN; */			wdsetctlr(dev, du);                        /* simulate opening partition 0 so write succeeds */                        /* dk->dk_openpart |= (1 << 0);            /* XXX */                        wlab = du->dk_wlabel;                        du->dk_wlabel = 1;                        error = writedisklabel(dev, wdstrategy, &du->dk_dd,wdpart(dev));                        /*dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;*/                        du->dk_wlabel = wlab;                }                break;#ifdef notyet	case DIOCGDINFOP:		*(struct disklabel **)addr = &(du->dk_dd);		break;	case DIOCWFORMAT:		if ((flag & FWRITE) == 0)			error = EBADF;		else {			register struct format_op *fop;			fop = (struct format_op *)addr;			aiov.iov_base = fop->df_buf;			aiov.iov_len = fop->df_count;			auio.uio_iov = &aiov;			auio.uio_iovcnt = 1;			auio.uio_resid = fop->df_count;			auio.uio_segflg = 0;			auio.uio_offset =				fop->df_startblk * du->dk_dd.d_secsize;			error = physio(wdformat, &rwdbuf[unit], dev, B_WRITE,				minphys, &auio);			fop->df_count -= auio.uio_resid;			fop->df_reg[0] = du->dk_status;			fop->df_reg[1] = du->dk_error;		}		break;#endif	default:		error = ENOTTY;		break;	}	return (error);}/*wdformat(bp)	struct buf *bp;{	bp->b_flags |= B_FORMAT;	return (wdstrategy(bp));}*//* * Routines to do raw IO for a unit. */wdread(dev, uio)			/* character read routine */	dev_t dev;	struct uio *uio;{	int unit = wdunit(dev) ;	if (unit >= NWD) return(ENXIO);	return(physio(wdstrategy, &rwdbuf[unit], dev, B_READ, minphys, uio));}wdwrite(dev, uio)			/* character write routine */	dev_t dev;	struct uio *uio;{	int unit = wdunit(dev) ;	if (unit >= NWD) return(ENXIO);	return(physio(wdstrategy, &rwdbuf[unit], dev, B_WRITE, minphys, uio));}wdsize(dev)	dev_t dev;{	register unit = wdunit(dev);	register part = wdpart(dev);	register struct disk *du;	register val ;	if (unit >= NWD) return(-1);	if (wddrives[unit].dk_state == 0) {		val = wdopen (dev, 0);		if (val < 0)			return (-1);	}	du = &wddrives[unit];	return((int)((u_long)du->dk_dd.d_partitions[part].p_size *		du->dk_dd.d_secsize / 512));}extern        char *vmmap;            /* poor name! */wddump(dev)			/* dump core after a system crash */	dev_t dev;{	register struct disk *du;	/* disk unit to do the IO */	register struct bt_bad *bt_ptr;	long	num;			/* number of sectors to write */	int	unit, part;	long	cyloff, blknum, blkcnt;	long	cylin, head, sector, stat;	long	secpertrk, secpercyl, nblocks, i;	char *addr;	extern	int Maxmem;	static  wddoingadump = 0 ;	extern CMAP1;	extern char CADDR1[];	#ifdef ARGOoutb(0x461,0);	/* disable failsafe timer */#endif	addr = (char *) 0;		/* starting address */	/* size of memory to dump */	num = Maxmem;	unit = wdunit(dev);		/* eventually support floppies? */	part = wdpart(dev);		/* file system */	/* check for acceptable drive number */	if (unit >= NWD) return(ENXIO);	du = &wddrives[unit];	/* was it ever initialized ? */	if (du->dk_state < OPEN) return (ENXIO) ;	/* Convert to disk sectors */	num = (u_long) num * NBPG / du->dk_dd.d_secsize;	/* check if controller active */	/*if (wdtab.b_active) return(EFAULT); */	if (wddoingadump) return(EFAULT);	secpertrk = du->dk_dd.d_nsectors;	secpercyl = du->dk_dd.d_secpercyl;	nblocks = du->dk_dd.d_partitions[part].p_size;	cyloff = du->dk_dd.d_partitions[part].p_offset / secpercyl;/*pg("xunit %x, nblocks %d, dumplo %d num %d\n", part,nblocks,dumplo,num);*/	/* check transfer bounds against partition size */	if ((dumplo < 0) || ((dumplo + num) > nblocks))		return(EINVAL);	/*wdtab.b_active = 1;		/* mark controller active for if we					   panic during the dump */	wddoingadump = 1  ;  i = 100000 ;	while ((inb(wdc+wd_status) & WDCS_BUSY) && (i-- > 0)) ;	outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));	outb(wdc+wd_command, WDCC_RESTORE | WD_STEP);	while (inb(wdc+wd_status) & WDCS_BUSY) ;	/* some compaq controllers require this ... */	wdsetctlr(dev, du);		blknum = dumplo;	while (num > 0) {#ifdef notdef		if (blkcnt > MAXTRANSFER) blkcnt = MAXTRANSFER;		if ((blknum + blkcnt - 1) / secpercyl != blknum / secpercyl)			blkcnt = secpercyl - (blknum % secpercyl);			    /* keep transfer within current cylinder */#endif		pmap_enter(kernel_pmap, vmmap, addr, VM_PROT_READ, TRUE);		/* compute disk address */		cylin = blknum / secpercyl;		head = (blknum % secpercyl) / secpertrk;		sector = blknum % secpertrk;		cylin += cyloff;#ifdef notyet		/* 		 * See if the current block is in the bad block list.		 * (If we have one.)		 */	    		for (bt_ptr = dkbad[unit].bt_bad;				bt_ptr->bt_cyl != -1; bt_ptr++) {			if (bt_ptr->bt_cyl > cylin)				/* Sorted list, and we passed our cylinder.					quit. */				break;			if (bt_ptr->bt_cyl == cylin &&				bt_ptr->bt_trksec == (head << 8) + sector) {			/*			 * Found bad block.  Calculate new block addr.			 * This starts at the end of the disk (skip the			 * last track which is used for the bad block list),			 * and works backwards to the front of the disk.			 */				blknum = (du->dk_dd.d_secperunit)					- du->dk_dd.d_nsectors					- (bt_ptr - dkbad[unit].bt_bad) - 1;				cylin = blknum / secpercyl;				head = (blknum % secpercyl) / secpertrk;				sector = blknum % secpertrk;				break;			}#endif		sector++;		/* origin 1 */		/* select drive.     */		outb(wdc+wd_sdh, WDSD_IBM | (unit<<4) | (head & 0xf));		while ((inb(wdc+wd_status) & WDCS_READY) == 0) ;		/* transfer some blocks */		outb(wdc+wd_sector, sector);		outb(wdc+wd_seccnt,1);		outb(wdc+wd_cyl_lo, cylin);		outb(wdc+wd_cyl_hi, cylin >> 8);#ifdef notdef		/* lets just talk about this first...*/		pg ("sdh 0%o sector %d cyl %d addr 0x%x",			inb(wdc+wd_sdh), inb(wdc+wd_sector),			inb(wdc+wd_cyl_hi)*256+inb(wdc+wd_cyl_lo), addr) ;#endif#ifdef ODYSSEUSif(cylin < 46 || cylin > 91)pg("oops");#endif#ifdef PRIAMif(cylin < 40 || cylin > 79)pg("oops");#endif		outb(wdc+wd_command, WDCC_WRITE);				/* Ready to send data?	*/		while ((inb(wdc+wd_status) & WDCS_DRQ) == 0) ;		if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ;		outsw (wdc+wd_data, CADDR1+((int)addr&(NBPG-1)), 256);		(int) addr += 512;		if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ;		/* Check data request (should be done).         */		if (inb(wdc+wd_status) & WDCS_DRQ) return(EIO) ;		/* wait for completion */		for ( i = 1000000 ; inb(wdc+wd_status) & WDCS_BUSY ; i--) {				if (i < 0) return (EIO) ;		}		/* error check the xfer */		if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ;		/* update block count */		num--;		blknum++ ;if (num % 100 == 0) printf(".") ;	}	return(0);}#endif

⌨️ 快捷键说明

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