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

📄 ide-floppy.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {			/* Error detected */#if IDEFLOPPY_DEBUG_LOG			printk(KERN_INFO "ide-floppy: %s: I/O error\n",				drive->name);#endif /* IDEFLOPPY_DEBUG_LOG */			rq->errors++;			if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {				printk(KERN_ERR "ide-floppy: I/O error in "					"request sense command\n");				return ide_do_reset(drive);			}			/* Retry operation */			idefloppy_retry_pc(drive);			/* queued, but not started */			return ide_stopped;		}		pc->error = 0;		if (floppy->failed_pc == pc)			floppy->failed_pc = NULL;		/* Command finished - Call the callback function */		pc->callback(drive);		return ide_stopped;	}#ifdef CONFIG_BLK_DEV_IDEDMA	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {		printk(KERN_ERR "ide-floppy: The floppy wants to issue "			"more interrupts in DMA mode\n");		(void) HWIF(drive)->ide_dma_off(drive);		return ide_do_reset(drive);	}#endif /* CONFIG_BLK_DEV_IDEDMA */	/* Get the number of bytes to transfer */	bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);	bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);	/* on this interrupt */	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);	if (ireason.b.cod) {		printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");		return ide_do_reset(drive);	}	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {		/* Hopefully, we will never get here */		printk(KERN_ERR "ide-floppy: We wanted to %s, ",			ireason.b.io ? "Write":"Read");		printk(KERN_ERR "but the floppy wants us to %s !\n",			ireason.b.io ? "Read":"Write");		return ide_do_reset(drive);	}	if (!test_bit(PC_WRITING, &pc->flags)) {		/* Reading - Check that we have enough space */		temp = pc->actually_transferred + bcount.all;		if (temp > pc->request_transfer) {			if (temp > pc->buffer_size) {				printk(KERN_ERR "ide-floppy: The floppy wants "					"to send us more data than expected "					"- discarding data\n");				idefloppy_discard_data(drive,bcount.all);				if (HWGROUP(drive)->handler != NULL)					BUG();				ide_set_handler(drive,						&idefloppy_pc_intr,						IDEFLOPPY_WAIT_CMD,						NULL);				return ide_started;			}#if IDEFLOPPY_DEBUG_LOG			printk(KERN_NOTICE "ide-floppy: The floppy wants to "				"send us more data than expected - "				"allowing transfer\n");#endif /* IDEFLOPPY_DEBUG_LOG */		}	}	if (test_bit(PC_WRITING, &pc->flags)) {		if (pc->buffer != NULL)			/* Write the current buffer */			HWIF(drive)->atapi_output_bytes(drive,						pc->current_position,						bcount.all);		else			idefloppy_output_buffers(drive, pc, bcount.all);	} else {		if (pc->buffer != NULL)			/* Read the current buffer */			HWIF(drive)->atapi_input_bytes(drive,						pc->current_position,						bcount.all);		else			idefloppy_input_buffers(drive, pc, bcount.all);	}	/* Update the current position */	pc->actually_transferred += bcount.all;	pc->current_position += bcount.all;	if (HWGROUP(drive)->handler != NULL)		BUG();	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */	return ide_started;}/* * This is the original routine that did the packet transfer. * It fails at high speeds on the Iomega ZIP drive, so there's a slower version * for that drive below. The algorithm is chosen based on drive type */static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive){	ide_startstop_t startstop;	idefloppy_floppy_t *floppy = drive->driver_data;	atapi_ireason_t ireason;	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {		printk(KERN_ERR "ide-floppy: Strange, packet command "				"initiated yet DRQ isn't asserted\n");		return startstop;	}	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);	if (!ireason.b.cod || ireason.b.io) {		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "				"issuing a packet command\n");		return ide_do_reset(drive);	}	if (HWGROUP(drive)->handler != NULL)		BUG();	/* Set the interrupt routine */	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);	/* Send the actual packet */	HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);	return ide_started;}/* * What we have here is a classic case of a top half / bottom half * interrupt service routine. In interrupt mode, the device sends * an interrupt to signal it's ready to receive a packet. However, * we need to delay about 2-3 ticks before issuing the packet or we * gets in trouble. * * So, follow carefully. transfer_pc1 is called as an interrupt (or * directly). In either case, when the device says it's ready for a  * packet, we schedule the packet transfer to occur about 2-3 ticks * later in transfer_pc2. */static int idefloppy_transfer_pc2 (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	/* Send the actual packet */	HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);	/* Timeout for the packet command */	return IDEFLOPPY_WAIT_CMD;}static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	ide_startstop_t startstop;	atapi_ireason_t ireason;	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {		printk(KERN_ERR "ide-floppy: Strange, packet command "				"initiated yet DRQ isn't asserted\n");		return startstop;	}	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);	if (!ireason.b.cod || ireason.b.io) {		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "				"while issuing a packet command\n");		return ide_do_reset(drive);	}	/* 	 * The following delay solves a problem with ATAPI Zip 100 drives	 * where the Busy flag was apparently being deasserted before the	 * unit was ready to receive data. This was happening on a	 * 1200 MHz Athlon system. 10/26/01 25msec is too short,	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually	 * used until after the packet is moved in about 50 msec.	 */	if (HWGROUP(drive)->handler != NULL)		BUG();	ide_set_handler(drive, 	  &idefloppy_pc_intr, 		/* service routine for packet command */	  floppy->ticks,		/* wait this long before "failing" */	  &idefloppy_transfer_pc2);	/* fail == transfer_pc2 */	return ide_started;}/* *	Issue a packet command */static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc){	idefloppy_floppy_t *floppy = drive->driver_data;	atapi_feature_t feature;	atapi_bcount_t bcount;	ide_handler_t *pkt_xfer_routine;#if IDEFLOPPY_DEBUG_BUGS	if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&	    pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {		printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "			"Two request sense in serial were issued\n");	}#endif /* IDEFLOPPY_DEBUG_BUGS */	if (floppy->failed_pc == NULL &&	    pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)		floppy->failed_pc = pc;	/* Set the current packet command */	floppy->pc = pc;	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES ||	    test_bit(PC_ABORT, &pc->flags)) {		/*		 *	We will "abort" retrying a packet command in case		 *	a legitimate error code was received.		 */		if (!test_bit(PC_ABORT, &pc->flags)) {			if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) {				printk(KERN_ERR "ide-floppy: %s: I/O error, "						"pc = %2x, key = %2x, "						"asc = %2x, ascq = %2x\n",						drive->name, pc->c[0],						floppy->sense_key,						floppy->asc, floppy->ascq);			}			/* Giving up */			pc->error = IDEFLOPPY_ERROR_GENERAL;		}		floppy->failed_pc = NULL;		pc->callback(drive);		return ide_stopped;	}#if IDEFLOPPY_DEBUG_LOG	printk (KERN_INFO "Retry number - %d\n", pc->retries);#endif /* IDEFLOPPY_DEBUG_LOG */	pc->retries++;	/* We haven't transferred any data yet */	pc->actually_transferred = 0;	pc->current_position = pc->buffer;	bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);#ifdef CONFIG_BLK_DEV_IDEDMA	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {		(void) HWIF(drive)->ide_dma_off(drive);	}#endif /* CONFIG_BLK_DEV_IDEDMA */	feature.all = 0;#ifdef CONFIG_BLK_DEV_IDEDMA	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {		if (test_bit(PC_WRITING, &pc->flags)) {			feature.b.dma = !HWIF(drive)->ide_dma_write(drive);		} else {			feature.b.dma = !HWIF(drive)->ide_dma_read(drive);		}	}#endif /* CONFIG_BLK_DEV_IDEDMA */	if (IDE_CONTROL_REG)		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);	/* Use PIO/DMA */	HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);	HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);	HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);#ifdef CONFIG_BLK_DEV_IDEDMA	if (feature.b.dma) {	/* Begin DMA, if necessary */		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);		(void) (HWIF(drive)->ide_dma_begin(drive));	}#endif /* CONFIG_BLK_DEV_IDEDMA */	/* Can we transfer the packet when we get the interrupt or wait? */	if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {		/* wait */		pkt_xfer_routine = &idefloppy_transfer_pc1;	} else {		/* immediate */		pkt_xfer_routine = &idefloppy_transfer_pc;	}		if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {		/* Issue the packet command */		ide_execute_command(drive, WIN_PACKETCMD, 				pkt_xfer_routine,				IDEFLOPPY_WAIT_CMD,				NULL);		return ide_started;	} else {		/* Issue the packet command */		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);		return (*pkt_xfer_routine) (drive);	}}static void idefloppy_rw_callback (ide_drive_t *drive){#if IDEFLOPPY_DEBUG_LOG		printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");#endif /* IDEFLOPPY_DEBUG_LOG */	idefloppy_do_end_request(drive, 1);	return;}static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent){#if IDEFLOPPY_DEBUG_LOG	printk(KERN_INFO "ide-floppy: creating prevent removal command, "		"prevent = %d\n", prevent);#endif /* IDEFLOPPY_DEBUG_LOG */	idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;	pc->c[4] = prevent;}static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc){	idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;	pc->c[7] = 255;	pc->c[8] = 255;	pc->request_transfer = 255;}static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,					      int flags){	idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;	pc->c[1] = 0x17;	memset(pc->buffer, 0, 12);	pc->buffer[1] = 0xA2;	/* Default format list header, u8 1: FOV/DCRT/IMM bits set */	if (flags & 1)				/* Verify bit on... */		pc->buffer[1] ^= 0x20;		/* ... turn off DCRT bit */	pc->buffer[3] = 8;	put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));	put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));	pc->buffer_size=12;	set_bit(PC_WRITING, &pc->flags);}/* *	A mode sense command is used to "sense" floppy parameters. */static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type){	u16 length = sizeof(idefloppy_mode_parameter_header_t);		idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD;	pc->c[1] = 0;	pc->c[2] = page_code + (type << 6);	switch (page_code) {		case IDEFLOPPY_CAPABILITIES_PAGE:			length += 12;			break;		case IDEFLOPPY_FLEXIBLE_DISK_PAGE:			length += 32;			break;		default:			printk(KERN_ERR "ide-floppy: unsupported page code "				"in create_mode_sense_cmd\n");	}	put_unaligned(htons(length), (u16 *) &pc->c[7]);	pc->request_transfer = length;}static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start){	idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_START_STOP_CMD;	pc->c[4] = start;}static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc){	idefloppy_init_pc(pc);	pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD;}static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector){	int block = sector / floppy->bs_factor;	int blocks = rq->nr_sectors / floppy->bs_factor;	#if IDEFLOPPY_DEBUG_LOG	printk("create_rw1%d_cmd: block == %d, blocks == %d\n",		2 * test_bit(IDEFLOPPY_USE_READ12, &floppy->flags),		block, blocks);#endif /* IDEFLOPPY_DEBUG_LOG */	idefloppy_init_pc(pc);	if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) {		pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD;		put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]);	} else {		pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD;		put_unaligned(htons(blocks), (u16 *) &pc->c[7]);	}	put_unaligned(htonl(block), (unsigned int *) &pc->c[2]);	pc->callback = &idefloppy_rw_callback;	pc->rq = rq;	pc->b_data = rq->buffer;	pc->b_count = rq->cmd == READ ? 0 : rq->bh->b_size;	if (rq->cmd == WRITE)		set_bit(PC_WRITING, &pc->flags);	pc->buffer = NULL;

⌨️ 快捷键说明

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