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

📄 fd1772.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		goto repeat;	}	if (type == 0) {		if (!floppy->disktype) {			Probing = 1;			floppy->disktype = disk_type + NUM_DISK_TYPES - 1;			floppy_sizes[drive] = floppy->disktype->blocks >> 1;			floppy->autoprobe = 1;		}	} else {		/* user supplied disk type */		--type;		if (type >= NUM_DISK_TYPES) {			printk("fd%d: invalid disk format", drive);			end_request(0);			goto repeat;		}		floppy->disktype = &disk_type[type];		floppy_sizes[drive] = disk_type[type].blocks >> 1;		floppy->autoprobe = 0;	}	if (CURRENT->sector + 1 > floppy->disktype->blocks) {		end_request(0);		goto repeat;	}	/* stop deselect timer */	del_timer(&motor_off_timer);	ReqCnt = 0;	ReqCmd = CURRENT->cmd;	ReqBlock = CURRENT->sector;	ReqBuffer = CURRENT->buffer;	setup_req_params(drive);	do_fd_action(drive);	return;      the_end:	finish_fdc();}static void fd1772_checkint(void){  extern int fdc1772_bytestogo;  /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/  if (fdc1772_fdc_int_done)    floppy_irqconsequencehandler();  if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);  if (fdc_busy) {    queue_task(&fd1772_tq,&tq_immediate);    mark_bh(IMMEDIATE_BH);  };};void do_fd_request(void){	unsigned long flags;	DPRINT(("do_fd_request for pid %d\n", current->pid));	if (fdc_busy) return;	save_flags(flags);	cli();	while (fdc_busy)		sleep_on(&fdc_wait);	fdc_busy = 1;	ENABLE_IRQ();	restore_flags(flags);	fdc1772_fdc_int_done = 0;	redo_fd_request();  queue_task(&fd1772_tq,&tq_immediate);  mark_bh(IMMEDIATE_BH);}static int invalidate_drive(int rdev){	/* invalidate the buffer track to force a reread */#ifdef TRACKBUFFER  BufferDrive = -1;#endif	set_bit(rdev & 3, &fake_change);	check_disk_change(rdev);	return 0;}static int fd_ioctl(struct inode *inode, struct file *filp,		    unsigned int cmd, unsigned long param){#define IOCTL_MODE_BIT 8#define OPEN_WRITE_BIT 16#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))	int drive, device;	device = inode->i_rdev;	switch (cmd) {		RO_IOCTLS(inode->i_rdev, param);	}	drive = MINOR(device);	if (!IOCTL_ALLOWED)		return -EPERM;	switch (cmd) {	case FDFMTBEG:		return 0;		/* case FDC1772LRPRM:  ??? DAG what does this do?? 		   unit[drive].disktype = NULL;		   floppy_sizes[drive] = MAX_DISK_SIZE;		   return invalidate_drive (device); */	case FDFMTEND:	case FDFLUSH:		return invalidate_drive(drive);	}	if (!suser())		return -EPERM;	if (drive < 0 || drive > 3)		return -EINVAL;	switch (cmd) {	default:		return -EINVAL;	}	return 0;}/* Initialize the 'unit' variable for drive 'drive' */static void fd_probe(int drive){	unit[drive].connected = 0;	unit[drive].disktype = NULL;	if (!fd_test_drive_present(drive))		return;	unit[drive].connected = 1;	unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */	unit[drive].steprate = FDC1772STEP_6;	MotorOn = 1;		/* from probe restore operation! */}/* This function tests the physical presence of a floppy drive (not * whether a disk is inserted). This is done by issuing a restore * command, waiting max. 2 seconds (that should be enough to move the * head across the whole disk) and looking at the state of the "TR00" * signal. This should now be raised if there is a drive connected * (and there is no hardware failure :-) Otherwise, the drive is * declared absent. */static int fd_test_drive_present(int drive){	unsigned long timeout;	unsigned char status;	int ok;	printk("fd_test_drive_present %d\n", drive);	if (drive > 1)		return (0);	return (1);		/* Simple hack for the moment - the autodetect doesn't seem to work on arc */	fd_select_drive(drive);	/* disable interrupt temporarily */	DISABLE_IRQ();	FDC1772_WRITE(FDC1772REG_TRACK, 0x00);	/* was ff00 why? */	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);	/*printk("fd_test_drive_present: Going into timeout loop\n"); */	for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; jiffies < timeout;) {		/*  What does this piece of atariism do? - query for an interrupt? */		/*  if (!(mfp.par_dt_reg & 0x20))		   break; */		/* Well this is my nearest guess - quit when we get an FDC interrupt */		if (IOC_FIQSTAT & 2)			break;	}	/*printk("fd_test_drive_present: Coming out of timeout loop\n"); */	status = FDC1772_READ(FDC1772REG_STATUS);	ok = (status & FDC1772STAT_TR00) != 0;	/*printk("fd_test_drive_present: ok=%d\n",ok); */	/* force interrupt to abort restore operation (FDC1772 would try	 * about 50 seconds!) */	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);	udelay(500);	status = FDC1772_READ(FDC1772REG_STATUS);	udelay(20);	/*printk("fd_test_drive_present: just before OK code %d\n",ok); */	if (ok) {		/* dummy seek command to make WP bit accessible */		FDC1772_WRITE(FDC1772REG_DATA, 0);		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);		printk("fd_test_drive_present: just before wait for int\n");		/* DAG: Guess means wait for interrupt */		while (!(IOC_FIQSTAT & 2));		printk("fd_test_drive_present: just after wait for int\n");		status = FDC1772_READ(FDC1772REG_STATUS);	}	printk("fd_test_drive_present: just before ENABLE_IRQ\n");	ENABLE_IRQ();	printk("fd_test_drive_present: about to return\n");	return (ok);}/* Look how many and which kind of drives are connected. If there are * floppies, additionally start the disk-change and motor-off timers. */static void config_types(void){	int drive, cnt = 0;	printk("Probing floppy drive(s):\n");	for (drive = 0; drive < FD_MAX_UNITS; drive++) {		fd_probe(drive);		if (unit[drive].connected) {			printk("fd%d\n", drive);			++cnt;		}	}	if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {		/* If FDC1772 is still busy from probing, give it another FORCI		 * command to abort the operation. If this isn't done, the FDC1772		 * will interrupt later and its IRQ line stays low, because		 * the status register isn't read. And this will block any		 * interrupts on this IRQ line :-(		 */		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);		udelay(500);		FDC1772_READ(FDC1772REG_STATUS);		udelay(20);	}	if (cnt > 0) {		START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);		if (cnt == 1)			fd_select_drive(0);		/*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */	}}/* * floppy_open check for aliasing (/dev/fd0 can be the same as * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */static int floppy_open(struct inode *inode, struct file *filp){	int drive;	int old_dev;	if (!filp) {		DPRINT(("Weird, open called with filp=0\n"));		return -EIO;	}	drive = MINOR(inode->i_rdev) & 3;	if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES)		return -ENXIO;	old_dev = fd_device[drive];	if (fd_ref[drive])		if (old_dev != inode->i_rdev)			return -EBUSY;	if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))		return -EBUSY;	if (filp->f_flags & O_EXCL)		fd_ref[drive] = -1;	else		fd_ref[drive]++;	fd_device[drive] = inode->i_rdev;	if (old_dev && old_dev != inode->i_rdev)		invalidate_buffers(old_dev);	/* Allow ioctls if we have write-permissions even if read-only open */	if (filp->f_mode & 2 || permission(inode, 2) == 0)		filp->f_mode |= IOCTL_MODE_BIT;	if (filp->f_mode & 2)		filp->f_mode |= OPEN_WRITE_BIT;	if (filp->f_flags & O_NDELAY)		return 0;	if (filp->f_mode & 3) {		check_disk_change(inode->i_rdev);		if (filp->f_mode & 2) {			if (unit[drive].wpstat) {				floppy_release(inode, filp);				return -EROFS;			}		}	}	return 0;}static void floppy_release(struct inode *inode, struct file *filp){	int drive;	drive = inode->i_rdev & 3;	if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))		/* if the file is mounted OR (writable now AND writable at open		   time) Linus: Does this cover all cases? */		block_fsync(inode, filp);	if (fd_ref[drive] < 0)		fd_ref[drive] = 0;	else if (!fd_ref[drive]--) {		printk("floppy_release with fd_ref == 0");		fd_ref[drive] = 0;	}}static struct file_operations floppy_fops ={	NULL,			/* lseek - default */	block_read,		/* read - general block-dev read */	block_write,		/* write - general block-dev write */	NULL,			/* readdir - bad */	NULL,			/* select */	fd_ioctl,		/* ioctl */	NULL,			/* mmap */	floppy_open,		/* open */	floppy_release,		/* release */	block_fsync,		/* fsync */	NULL,			/* fasync */	check_floppy_change,	/* media_change */	floppy_revalidate,	/* revalidate */};int floppy_init(void){	int i;	if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {		printk("Unable to get major %d for floppy\n", MAJOR_NR);		return 1;	}	if (request_dma(FLOPPY_DMA, "fd1772")) {		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);		return 1;	};	if (request_dma(FIQ_FD1772, "fd1772 end")) {		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);		free_dma(FLOPPY_DMA);		return 1;	};	enable_dma(FIQ_FD1772);	/* This inserts a call to our command end routine */	/* initialize variables */	SelectedDrive = -1;#ifdef TRACKBUFFER  BufferDrive = -1;#endif	/* initialize check_change timer */	timer_table[FLOPPY_TIMER].fn = check_change;	timer_active &= ~(1 << FLOPPY_TIMER);#ifdef TRACKBUFFER  DMABuffer = (char *)kmalloc((MAX_SECTORS+1)*512,GFP_KERNEL); /* Atari uses 512 - I want to eventually cope with 1K sectors */  TrackBuffer = DMABuffer + 512;#else	/* Allocate memory for the DMAbuffer - on the Atari this takes it	   out of some special memory... */	DMABuffer = (char *) kmalloc(2048);	/* Copes with pretty large sectors */#endif#ifdef TRACKBUFFER    BufferDrive = BufferSide = BufferTrack = -1;#endif	for (i = 0; i < FD_MAX_UNITS; i++) {		unit[i].track = -1;	}	for (i = 0; i < 256; i++)		if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)			floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;		else			floppy_sizes[i] = MAX_DISK_SIZE;	blk_size[MAJOR_NR] = floppy_sizes;	blksize_size[MAJOR_NR] = floppy_blocksizes;	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;	config_types();	return 0;}/* Just a dummy at the moment */void floppy_setup(char *str, int *ints){}void floppy_eject(void) {}

⌨️ 快捷键说明

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