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

📄 swim3.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct floppy_state *fs = (struct floppy_state *) data;	volatile struct swim3 *sw = fs->swim3;	fs->timeout_pending = 0;	if (fs->state == settling) {		printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n",		       sw->select, sw->control, sw->status, sw->intr, sw->intr_enable);	}	out_8(&sw->control_bic, DO_SEEK);	out_8(&sw->select, RELAX);	out_8(&sw->intr_enable, 0);	if (fs->state == settling && swim3_readbit(fs, SEEK_COMPLETE)) {		/* printk(KERN_DEBUG "swim3: missed settling interrupt\n"); */		fs->state = locating;		act(fs);		return;	}	printk(KERN_ERR "swim3: seek timeout\n");	end_request(0);	fs->state = idle;	start_request(fs);}static void xfer_timeout(unsigned long data){	struct floppy_state *fs = (struct floppy_state *) data;	volatile struct swim3 *sw = fs->swim3;	struct dbdma_regs *dr = fs->dma;	struct dbdma_cmd *cp = fs->dma_cmd;	unsigned long s;	fs->timeout_pending = 0;	st_le32(&dr->control, RUN << 16);	out_8(&sw->intr_enable, 0);	out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);	out_8(&sw->select, RELAX);	if (CURRENT->cmd == WRITE)		++cp;	if (ld_le16(&cp->xfer_status) != 0)		s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9);	else		s = 0;	CURRENT->sector += s;	CURRENT->current_nr_sectors -= s;	printk(KERN_ERR "swim3: timeout %sing sector %ld\n",	       (CURRENT->cmd==WRITE? "writ": "read"), CURRENT->sector);	end_request(0);	fs->state = idle;	start_request(fs);}static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct floppy_state *fs = (struct floppy_state *) dev_id;	volatile struct swim3 *sw = fs->swim3;	int intr, err, n;	int stat, resid;	struct dbdma_regs *dr;	struct dbdma_cmd *cp;	err = in_8(&sw->error);	intr = in_8(&sw->intr);#if 0	printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);#endif	if ((intr & ERROR_INTR) && fs->state != do_transfer)		printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n",		       fs->state, CURRENT->cmd, intr, err);	switch (fs->state) {	case locating:		if (intr & SEEN_SECTOR) {			out_8(&sw->control_bic, DO_ACTION);			out_8(&sw->select, RELAX);			out_8(&sw->intr_enable, 0);			del_timer(&fs->timeout);			fs->timeout_pending = 0;			if (sw->ctrack == 0xff) {				printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");				fs->cur_cyl = -1;				if (fs->retries > 5) {					end_request(0);					fs->state = idle;					start_request(fs);				} else {					fs->state = jogging;					act(fs);				}				break;			}			fs->cur_cyl = sw->ctrack;			fs->cur_sector = sw->csect;			if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl)				printk(KERN_ERR "swim3: expected cyl %d, got %d\n",				       fs->expect_cyl, fs->cur_cyl);			fs->state = do_transfer;			act(fs);		}		break;	case seeking:	case jogging:		if (sw->nseek == 0) {			out_8(&sw->control_bic, DO_SEEK);			out_8(&sw->select, RELAX);			out_8(&sw->intr_enable, 0);			del_timer(&fs->timeout);			fs->timeout_pending = 0;			if (fs->state == seeking)				++fs->retries;			fs->state = settling;			act(fs);		}		break;	case settling:		out_8(&sw->intr_enable, 0);		del_timer(&fs->timeout);		fs->timeout_pending = 0;		act(fs);		break;	case do_transfer:		if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0)			break;		dr = fs->dma;		cp = fs->dma_cmd;		st_le32(&dr->control, RUN << 16);		out_8(&sw->intr_enable, 0);		out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);		out_8(&sw->select, RELAX);		del_timer(&fs->timeout);		fs->timeout_pending = 0;		if (CURRENT->cmd == WRITE)			++cp;		stat = ld_le16(&cp->xfer_status);		resid = ld_le16(&cp->res_count);		if (intr & ERROR_INTR) {			n = fs->scount - 1 - resid / 512;			if (n > 0) {				CURRENT->sector += n;				CURRENT->current_nr_sectors -= n;				CURRENT->buffer += n * 512;				fs->req_sector += n;			}			if (fs->retries < 5) {				++fs->retries;				act(fs);			} else {				printk("swim3: error %sing block %ld (err=%x)\n",				       CURRENT->cmd == WRITE? "writ": "read",				       CURRENT->sector, err);				end_request(0);				fs->state = idle;			}		} else {			if ((stat & ACTIVE) == 0 || resid != 0) {				/* musta been an error */				printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);				printk(KERN_ERR "  state=%d, cmd=%x, intr=%x, err=%x\n",				       fs->state, CURRENT->cmd, intr, err);				end_request(0);				fs->state = idle;				start_request(fs);				break;			}			CURRENT->sector += fs->scount;			CURRENT->current_nr_sectors -= fs->scount;			CURRENT->buffer += fs->scount * 512;			if (CURRENT->current_nr_sectors <= 0) {				end_request(1);				fs->state = idle;			} else {				fs->req_sector += fs->scount;				if (fs->req_sector > fs->secpertrack) {					fs->req_sector -= fs->secpertrack;					if (++fs->head > 1) {						fs->head = 0;						++fs->req_cyl;					}				}				act(fs);			}		}		if (fs->state == idle)			start_request(fs);		break;	default:		printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state);	}}/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs){}*/static int grab_drive(struct floppy_state *fs, enum swim_state state,		      int interruptible){	unsigned long flags;	save_flags(flags);	cli();	if (fs->state != idle) {		++fs->wanted;		while (fs->state != available) {			if (interruptible && signal_pending(current)) {				--fs->wanted;				restore_flags(flags);				return -EINTR;			}			interruptible_sleep_on(&fs->wait);		}		--fs->wanted;	}	fs->state = state;	restore_flags(flags);	return 0;}static void release_drive(struct floppy_state *fs){	unsigned long flags;	save_flags(flags);	cli();	fs->state = idle;	start_request(fs);	restore_flags(flags);}static int fd_eject(struct floppy_state *fs){	int err, n;	err = grab_drive(fs, ejecting, 1);	if (err)		return err;	swim3_action(fs, EJECT);	for (n = 2*HZ; n > 0; --n) {		if (swim3_readbit(fs, RELAX))			break;		if (signal_pending(current)) {			err = -EINTR;			break;		}		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(1);	}	fs->ejected = 1;	release_drive(fs);	return err;}int swim3_fd_eject(int devnum){	if (devnum >= floppy_count)		return -ENODEV;	/* Do not check this - this function should ONLY be called early	 * in the boot process! */	/* if (floppy_states[devnum].ref_count != 1) return -EBUSY; */	return fd_eject(&floppy_states[devnum]);}static struct floppy_struct floppy_type =	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL };	/*  7 1.44MB 3.5"   */static int floppy_ioctl(struct inode *inode, struct file *filp,			unsigned int cmd, unsigned long param){	struct floppy_state *fs;	int err;	int devnum = MINOR(inode->i_rdev);	if (devnum >= floppy_count)		return -ENODEV;			if ((cmd & 0x80) && !suser())		return -EPERM;	fs = &floppy_states[devnum];	if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))		return -ENXIO;	switch (cmd) {	case FDEJECT:		if (fs->ref_count != 1)			return -EBUSY;		err = fd_eject(fs);		return err;	case FDGETPRM:	        err = copy_to_user((void *) param, (void *) &floppy_type,				   sizeof(struct floppy_struct));		return err;	}	return -ENOIOCTLCMD;}static int floppy_open(struct inode *inode, struct file *filp){	struct floppy_state *fs;	volatile struct swim3 *sw;	int n, err;	int devnum = MINOR(inode->i_rdev);	if (devnum >= floppy_count)		return -ENODEV;	if (filp == 0)		return -EIO;			fs = &floppy_states[devnum];	sw = fs->swim3;	err = 0;	if (fs->ref_count == 0) {		if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))			return -ENXIO;		out_8(&sw->mode, 0x95);		out_8(&sw->control_bic, 0xff);		out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);		udelay(10);		out_8(&sw->intr_enable, 0);		out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);		swim3_action(fs, MOTOR_ON);		fs->write_prot = -1;		fs->cur_cyl = -1;		for (n = HZ; n > 0; --n) {			if (swim3_readbit(fs, SEEK_COMPLETE))				break;			if (signal_pending(current)) {				err = -EINTR;				break;			}			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(1);		}		if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0				 || swim3_readbit(fs, DISK_IN) == 0))			err = -ENXIO;		swim3_action(fs, 9);	} else if (fs->ref_count == -1 || filp->f_flags & O_EXCL)		return -EBUSY;	if (err == 0 && (filp->f_flags & O_NDELAY) == 0	    && (filp->f_mode & 3)) {		check_disk_change(inode->i_rdev);		if (fs->ejected)			err = -ENXIO;	}	if (err == 0 && (filp->f_mode & 2)) {		if (fs->write_prot < 0)			fs->write_prot = swim3_readbit(fs, WRITE_PROT);		if (fs->write_prot)			err = -EROFS;	}	if (err) {		if (fs->ref_count == 0) {			swim3_action(fs, MOTOR_OFF);			out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE);		}		return err;	}	if (filp->f_flags & O_EXCL)		fs->ref_count = -1;	else		++fs->ref_count;	return 0;}static int floppy_release(struct inode *inode, struct file *filp){	struct floppy_state *fs;	volatile struct swim3 *sw;	int devnum = MINOR(inode->i_rdev);	if (devnum >= floppy_count)		return -ENODEV;	fs = &floppy_states[devnum];	sw = fs->swim3;	if (fs->ref_count > 0 && --fs->ref_count == 0) {		swim3_action(fs, MOTOR_OFF);		out_8(&sw->control_bic, 0xff);	}	return 0;}static int floppy_check_change(kdev_t dev){	struct floppy_state *fs;	int devnum = MINOR(dev);	if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))		return 0;			fs = &floppy_states[devnum];	return fs->ejected;}static int floppy_revalidate(kdev_t dev){	struct floppy_state *fs;	volatile struct swim3 *sw;	int ret, n;	int devnum = MINOR(dev);	if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))		return 0;	fs = &floppy_states[devnum];	if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))		return -ENXIO;	sw = fs->swim3;	grab_drive(fs, revalidating, 0);	out_8(&sw->intr_enable, 0);	out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);	swim3_action(fs, MOTOR_ON);	fs->write_prot = -1;	fs->cur_cyl = -1;	for (n = HZ; n > 0; --n) {		if (swim3_readbit(fs, SEEK_COMPLETE))			break;		if (signal_pending(current))			break;		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(1);	}	ret = swim3_readbit(fs, SEEK_COMPLETE) == 0		|| swim3_readbit(fs, DISK_IN) == 0;	if (ret)		swim3_action(fs, MOTOR_OFF);	else {		fs->ejected = 0;		swim3_action(fs, 9);	}	release_drive(fs);	return ret;}static void floppy_off(unsigned int nr){}static struct block_device_operations floppy_fops = {	open:			floppy_open,	release:		floppy_release,	ioctl:			floppy_ioctl,	check_media_change:	floppy_check_change,	revalidate:		floppy_revalidate,};int swim3_init(void){	struct device_node *swim;	swim = find_devices("floppy");	while (swim && (floppy_count < MAX_FLOPPIES))	{		swim3_add_device(swim);		swim = swim->next;	}	swim = find_devices("swim3");	while (swim && (floppy_count < MAX_FLOPPIES))	{		swim3_add_device(swim);		swim = swim->next;	}	if (floppy_count > 0)	{		if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {			printk(KERN_ERR "Unable to get major %d for floppy\n",			       MAJOR_NR);			return -EBUSY;		}		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);		blksize_size[MAJOR_NR] = floppy_blocksizes;		blk_size[MAJOR_NR] = floppy_sizes;	}	return 0;}static int swim3_add_device(struct device_node *swim){	struct device_node *mediabay;	struct floppy_state *fs = &floppy_states[floppy_count];		if (swim->n_addrs < 2)	{		printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n",		       swim->n_addrs, swim->n_intrs);		return -EINVAL;	}	if (swim->n_intrs < 2)	{		printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n",		       swim->n_addrs, swim->n_intrs);		return -EINVAL;	}	mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL;	if (mediabay == NULL)		feature_set(swim, FEATURE_SWIM3_enable);		memset(fs, 0, sizeof(*fs));	fs->state = idle;	fs->swim3 = (volatile struct swim3 *) ioremap(swim->addrs[0].address, 0x200);	fs->dma = (struct dbdma_regs *) ioremap(swim->addrs[1].address, 0x200);	fs->swim3_intr = swim->intrs[0].line;	fs->dma_intr = swim->intrs[1].line;	fs->cur_cyl = -1;	fs->cur_sector = -1;	fs->secpercyl = 36;	fs->secpertrack = 18;	fs->total_secs = 2880;	fs->media_bay = mediabay;	init_waitqueue_head(&fs->wait);	fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);	memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));	st_le16(&fs->dma_cmd[1].command, DBDMA_STOP);	if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {		printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr);		feature_clear(swim, FEATURE_SWIM3_enable);		return -EBUSY;	}/*	if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {		printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",		       fs->dma_intr);		feature_clear(swim, FEATURE_SWIM3_enable);		return -EBUSY;	}*/	init_timer(&fs->timeout);	do_floppy = NULL;	printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,		mediabay ? "in media bay" : "");	floppy_count++;		return 0;}

⌨️ 快捷键说明

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