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

📄 mfmhd.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096,			mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors,			mfm_info[drive].lowcurrent, mfm_info[drive].precomp);	mfm[drive << 6].start_sect = 0;	mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;}#ifdef MFM_AUTODETECT_DRIVES/* * Attempt to detect a drive and find its geometry.  The drive has already been * specified... * * We first recalibrate the disk, then try to probe sectors, heads and then * cylinders.  NOTE! the cylinder probe may break drives.  The xd disk driver * does something along these lines, so I assume that most drives are up to * this mistreatment... */static int mfm_detectdrive (int drive){	unsigned int mingeo[3], maxgeo[3];	unsigned int attribute, need_recal = 1;	unsigned char cmdb[8];	memset (mingeo, 0, sizeof (mingeo));	maxgeo[0] = mfm_info[drive].sectors;	maxgeo[1] = mfm_info[drive].heads;	maxgeo[2] = mfm_info[drive].cylinders;	cmdb[0] = drive + 1;	cmdb[6] = 0;	cmdb[7] = 1;	for (attribute = 0; attribute < 3; attribute++) {		while (mingeo[attribute] != maxgeo[attribute]) {			unsigned int variable;			variable = (maxgeo[attribute] + mingeo[attribute]) >> 1;			cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0;			if (need_recal) {				int tries = 5;				do {					issue_command (CMD_RCLB, cmdb, 2);					wait_for_completion ();					wait_for_command_end ();					if  (result[1] == 0x20)						break;				} while (result[1] && --tries);				if (result[1]) {					outw (CMD_RCAL, MFM_COMMAND);					return 0;				}				need_recal = 0;			}			switch (attribute) {			case 0:				cmdb[5] = variable;				issue_command (CMD_CMPD, cmdb, 8);				break;			case 1:				cmdb[1] = variable;				cmdb[4] = variable;				issue_command (CMD_CMPD, cmdb, 8);				break;			case 2:				cmdb[2] = variable >> 8;				cmdb[3] = variable;				issue_command (CMD_SEK, cmdb, 4);				break;			}			wait_for_completion ();			wait_for_command_end ();			switch (result[1]) {			case 0x00:			case 0x50:				mingeo[attribute] = variable + 1;				break;			case 0x20:				outw (CMD_RCAL, MFM_COMMAND);				return 0;			case 0x24:				need_recal = 1;			default:				maxgeo[attribute] = variable;				break;			}		}	}	mfm_info[drive].cylinders  = mingeo[2];	mfm_info[drive].lowcurrent = mingeo[2];	mfm_info[drive].precomp    = mingeo[2] / 2;	mfm_info[drive].heads 	   = mingeo[1];	mfm_info[drive].sectors	   = mingeo[0];	outw (CMD_RCAL, MFM_COMMAND);	return 1;}#endif/* * Initialise all drive information for this controller. */static int mfm_initdrives(void){	int drive;	if (number_mfm_drives > MFM_MAXDRIVES) {		number_mfm_drives = MFM_MAXDRIVES;		printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n");	}	for (drive = 0; drive < number_mfm_drives; drive++) {		mfm_info[drive].lowcurrent = 1;		mfm_info[drive].precomp    = 1;		mfm_info[drive].cylinder   = -1;		mfm_info[drive].errors.recal  = 0;		mfm_info[drive].errors.report = 0;		mfm_info[drive].errors.abort  = 4;#ifdef MFM_AUTODETECT_DRIVES		mfm_info[drive].cylinders  = 1024;		mfm_info[drive].heads	   = 8;		mfm_info[drive].sectors	   = 64;		{			unsigned char cmdb[16];			mfm_setupspecify (drive, cmdb);			cmdb[1] &= ~0x81;			issue_command (CMD_SPC, cmdb, 16);			wait_for_completion ();			if (!mfm_detectdrive (drive)) {				mfm_info[drive].cylinders = 0;				mfm_info[drive].heads     = 0;				mfm_info[drive].sectors   = 0;			}			cmdb[0] = cmdb[1] = 0;			issue_command (CMD_CKV, cmdb, 2);		}#else		mfm_info[drive].cylinders  = 1;	/* its going to have to figure it out from the partition info */		mfm_info[drive].heads      = 4;		mfm_info[drive].sectors    = 32;#endif	}	return number_mfm_drives;}/* * The 'front' end of the mfm driver follows... */static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg){	struct hd_geometry *geo = (struct hd_geometry *) arg;	int dev, err;	if (!inode || !inode->i_rdev)		return -EINVAL;	dev = DEVICE_NR(MINOR(inode->i_rdev)), err;	if (dev >= mfm_drives)		return -EINVAL;	switch (cmd) {	case HDIO_GETGEO:		if (!arg)			return -EINVAL;		err = verify_area (VERIFY_WRITE, geo, sizeof(*geo));		if (err)			return err;		put_user (mfm_info[dev].heads, &geo->heads);		put_user (mfm_info[dev].sectors, &geo->sectors);		put_user (mfm_info[dev].cylinders, &geo->cylinders);		put_user (mfm[MINOR(inode->i_rdev)].start_sect, &geo->start);		return 0;	case BLKRASET:		if (!suser())			return -EACCES;		if (arg > 0xff)			return -EINVAL;		read_ahead[MAJOR(inode->i_rdev)] = arg;		return 0;	case BLKRAGET:		if (!arg)			return -EINVAL;		err = verify_area (VERIFY_WRITE, (long *) arg, sizeof (long));		if (err)			return err;		put_user(read_ahead[MAJOR(inode->i_rdev)], (long *)arg);		return 0;	case BLKGETSIZE:		if (!arg)			return -EINVAL;		err = verify_area (VERIFY_WRITE, (long *) arg, sizeof (long));		if (err)			 return err;		put_user (mfm[MINOR(inode->i_rdev)].nr_sects, (long *)arg);		return 0;	case BLKFLSBUF:		if (!suser())			return -EACCES;		if (!inode->i_rdev)			return -EINVAL;		fsync_dev(inode->i_rdev);		invalidate_buffers(inode->i_rdev);		return 0;	case BLKRRPART:		return mfm_reread_partitions(inode->i_rdev);	RO_IOCTLS(inode->i_rdev, arg);	default:		return -EINVAL;	}}static int mfm_open(struct inode *inode, struct file *file){	int dev = DEVICE_NR(MINOR(inode->i_rdev));	if (dev >= mfm_drives)		return -ENODEV;	while (mfm_info[dev].busy)		sleep_on (&mfm_wait_open);	mfm_info[dev].access_count++;	return 0;}/* * Releasing a block device means we sync() it, so that it can safely * be forgotten about... */static void mfm_release(struct inode *inode, struct file *file){	sync_dev(inode->i_rdev);	mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--;}/* * This is to handle various kernel command line parameters * specific to this driver. */void mfm_setup(char *str, int *ints){	return;}/* * Set the CHS from the ADFS boot block if it is present.  This is not ideal * since if there are any non-ADFS partitions on the disk, this won't work! * Hence, I want to get rid of this... */void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,		     unsigned long discsize, unsigned int secsize){	int drive = MINOR(dev) >> 6;	if (mfm_info[drive].cylinders == 1) {		mfm_info[drive].sectors = secsptrack;		mfm_info[drive].heads = heads;		mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);		if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {			printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6));			/* These values are fairly arbitary, but are there so that if your			 * lucky you can pick apart your disc to find out what is going on -			 * I reckon these figures won't hurt MOST drives			 */			mfm_info[drive].sectors = 32;			mfm_info[drive].heads = 4;			mfm_info[drive].cylinders = 512;		}		if (raw_cmd.dev == drive)			mfm_specify ();		mfm_geometry (drive);	}}static void mfm_geninit (struct gendisk *gdev);static struct gendisk mfm_gendisk = {	MAJOR_NR,		/* Major number */	"mfm",			/* Major name */	6,			/* Bits to shift to get real from partition */	1 << 6,			/* Number of partitions per real */	MFM_MAXDRIVES,		/* maximum number of real */	mfm_geninit,		/* init function */	mfm,			/* hd struct */	mfm_sizes,		/* block sizes */	0,			/* number */	(void *) mfm_info,	/* internal */	NULL			/* next */};static void mfm_geninit (struct gendisk *gdev){	int i;	mfm_drives = mfm_initdrives();	printk("mfm: detected %d hard drive%s\n", mfm_drives, mfm_drives == 1 ? "" : "s");	gdev->nr_real = mfm_drives;	for (i = 0; i < mfm_drives; i++)		mfm_geometry (i);	if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))		printk("mfm: unable to get IRQ%d\n", mfm_irq);	if (mfm_irqenable)		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */	for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {		mfm_blocksizes[i] = 1024;	/* Can't increase this - if you do all hell breaks loose */		mfm_sectsizes[i] = 512;	}	blksize_size[MAJOR_NR] = mfm_blocksizes;	hardsect_size[MAJOR_NR] = mfm_sectsizes;}void xd_manual_geo_init (char *command,int *integers) {  printk("MFM:Manual setting of geometry not presently supported\n");}static struct file_operations mfm_fops ={	NULL,			/* lseek - default */	block_read,		/* read - general block-dev read */	block_write,		/* write - general block-dev write */	NULL,			/* readdir - bad */	NULL,			/* select */	mfm_ioctl,		/* ioctl */	NULL,			/* mmap */	mfm_open,		/* open */	mfm_release,		/* release */	block_fsync		/* fsync */};static struct expansion_card *ecs;/* * See if there is a controller at the address presently at mfm_addr * * We check to see if the controller is busy - if it is, we abort it first, * and check that the chip is no longer busy after at least 180 clock cycles. * We then issue a command and check that the BSY or CPR bits are set. */static int mfm_probecontroller (unsigned int mfm_addr){	if (check_region (mfm_addr, 10))		return 0;	if (inw (MFM_STATUS) & STAT_BSY) {		outw (CMD_ABT, MFM_COMMAND);		udelay (50);		if (inw (MFM_STATUS) & STAT_BSY)			return 0;	}	if (inw (MFM_STATUS) & STAT_CED)		outw (CMD_RCAL, MFM_COMMAND);	outw (CMD_SEK, MFM_COMMAND);	if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {		unsigned int count = 2000;		while (inw (MFM_STATUS) & STAT_BSY) {			udelay (500);			if (!--count)				return 0;		}		outw (CMD_RCAL, MFM_COMMAND);	}	return 1;}/* * Look for a MFM controller - first check the motherboard, then the podules * The podules have an extra interrupt enable that needs to be played with * * The HDC is accessed at MEDIUM IOC speeds. */int mfm_init (void){	unsigned char irqmask;	if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);		return -1;	}	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {		mfm_addr	= ONBOARD_MFM_ADDRESS;		mfm_IRQPollLoc	= IOC_IRQSTATB;		mfm_irqenable	= 0;		mfm_irq		= IRQ_HARDDISK;		irqmask		= 0x08;			/* IL3 pin */	} else {		ecs = ecard_find(0, mfm_cids);		if (!ecs) {			mfm_addr = 0;			return -1;		}		mfm_addr	= ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800;		mfm_IRQPollLoc	= mfm_addr + 0x400;		mfm_irqenable	= mfm_IRQPollLoc;		mfm_irq		= ecs->irq;		irqmask		= 0x08;		ecard_claim(ecs);	}	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);	request_region (mfm_addr, 10, "mfm");	/* Stuff for the assembler routines to get to */	hdc63463_baseaddress	= ioaddr(mfm_addr);	hdc63463_irqpolladdress	= ioaddr(mfm_IRQPollLoc);	hdc63463_irqpollmask	= irqmask;	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB?) read ahread */#ifndef MODULE	mfm_gendisk.next = gendisk_head;	gendisk_head = &mfm_gendisk;#endif	Busy = 0;	lastspecifieddrive = -1;	return 0;}/* * This routine is called to flush all partitions and partition tables * for a changed MFM disk, and then re-read the new partition table. * If we are revalidating due to an ioctl, we have USAGE == 1. */static int mfm_reread_partitions(kdev_t dev){	unsigned int start, i, maxp, target = DEVICE_NR(MINOR(dev));	unsigned long flags;	save_flags_cli(flags);	if (mfm_info[target].busy || mfm_info[target].access_count > 1) {		restore_flags (flags);		return -EBUSY;	}	mfm_info[target].busy = 1;	restore_flags (flags);	maxp = mfm_gendisk.max_p;	start = target << mfm_gendisk.minor_shift;	for (i = maxp - 1; i >= 0; i--) {		int minor = start + i;		kdev_t devi = MKDEV(MAJOR_NR, minor);		sync_dev (devi);		invalidate_inodes (devi);		invalidate_buffers (devi);		mfm_gendisk.part[minor].start_sect = 0;		mfm_gendisk.part[minor].nr_sects = 0;	}	mfm_gendisk.part[start].nr_sects = mfm_info[target].heads *	    mfm_info[target].cylinders * mfm_info[target].sectors / 2;	resetup_one_dev(&mfm_gendisk, target);	mfm_info[target].busy = 0;	wake_up (&mfm_wait_open);	return 0;}#ifdef MODULEint init_module(void){	int ret;	ret = mfm_init();	if (!ret)		mfm_geninit(&mfm_gendisk);	return ret;}void cleanup_module(void){	if (ecs && mfm_irqenable)		outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */	free_irq(mfm_irq, NULL);	unregister_blkdev(MAJOR_NR, "mfm");	if (ecs)		ecard_release(ecs);	if (mfm_addr)		release_region(mfm_addr, 10);}#endif

⌨️ 快捷键说明

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