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

📄 ide-floppy.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned	ansi_version	:3;	/* ANSI Version */	unsigned	ecma_version	:3;	/* ECMA Version */	unsigned	iso_version	:2;	/* ISO Version */	unsigned	response_format :4;	/* Response Data Format */	unsigned	reserved3_45	:2;	/* Reserved */	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */	unsigned	reserved3_7	:1;	/* AENC - Reserved */#elif defined(__BIG_ENDIAN_BITFIELD)	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */	unsigned	device_type	:5;	/* Peripheral Device Type */	unsigned	rmb		:1;	/* Removable Medium Bit */	unsigned	reserved1_6t0	:7;	/* Reserved */	unsigned	iso_version	:2;	/* ISO Version */	unsigned	ecma_version	:3;	/* ECMA Version */	unsigned	ansi_version	:3;	/* ANSI Version */	unsigned	reserved3_7	:1;	/* AENC - Reserved */	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */	unsigned	reserved3_45	:2;	/* Reserved */	unsigned	response_format :4;	/* Response Data Format */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif	u8		additional_length;	/* Additional Length (total_length-4) */	u8		rsv5, rsv6, rsv7;	/* Reserved */	u8		vendor_id[8];		/* Vendor Identification */	u8		product_id[16];		/* Product Identification */	u8		revision_level[4];	/* Revision Level */	u8		vendor_specific[20];	/* Vendor Specific - Optional */	u8		reserved56t95[40];	/* Reserved - Optional */						/* Additional information may be returned */} idefloppy_inquiry_result_t;/* *	REQUEST SENSE packet command result - Data Format. */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD)	unsigned	error_code	:7;	/* Current error (0x70) */	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */	u8		reserved1	:8;	/* Reserved */	unsigned	sense_key	:4;	/* Sense Key */	unsigned	reserved2_4	:1;	/* Reserved */	unsigned	ili		:1;	/* Incorrect Length Indicator */	unsigned	reserved2_67	:2;#elif defined(__BIG_ENDIAN_BITFIELD)	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */	unsigned	error_code	:7;	/* Current error (0x70) */	u8		reserved1	:8;	/* Reserved */	unsigned	reserved2_67	:2;	unsigned	ili		:1;	/* Incorrect Length Indicator */	unsigned	reserved2_4	:1;	/* Reserved */	unsigned	sense_key	:4;	/* Sense Key */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif	u32		information __attribute__ ((packed));	u8		asl;			/* Additional sense length (n-7) */	u32		command_specific;	/* Additional command specific information */	u8		asc;			/* Additional Sense Code */	u8		ascq;			/* Additional Sense Code Qualifier */	u8		replaceable_unit_code;	/* Field Replaceable Unit Code */	u8		sksv[3];	u8		pad[2];			/* Padding to 20 bytes */} idefloppy_request_sense_result_t;/* *	Pages of the SELECT SENSE / MODE SENSE packet commands. */#define	IDEFLOPPY_CAPABILITIES_PAGE	0x1b#define IDEFLOPPY_FLEXIBLE_DISK_PAGE	0x05/* *	Mode Parameter Header for the MODE SENSE packet command */typedef struct {	u16		mode_data_length;	/* Length of the following data transfer */	u8		medium_type;		/* Medium Type */#if defined(__LITTLE_ENDIAN_BITFIELD)	unsigned	reserved3	:7;	unsigned	wp		:1;	/* Write protect */#elif defined(__BIG_ENDIAN_BITFIELD)	unsigned	wp		:1;	/* Write protect */	unsigned	reserved3	:7;#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif	u8		reserved[4];} idefloppy_mode_parameter_header_t;#define IDEFLOPPY_MIN(a,b)	((a)<(b) ? (a):(b))#define	IDEFLOPPY_MAX(a,b)	((a)>(b) ? (a):(b))/* *	Too bad. The drive wants to send us data which we are not ready to accept. *	Just throw it away. */static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount){	while (bcount--)		(void) HWIF(drive)->INB(IDE_DATA_REG);}#if IDEFLOPPY_DEBUG_BUGSstatic void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount){	while (bcount--)		HWIF(drive)->OUTB(0, IDE_DATA_REG);}#endif /* IDEFLOPPY_DEBUG_BUGS */static int idefloppy_end_request (ide_drive_t *drive, int uptodate){	struct request *rq;	unsigned long flags;	int ret = 1;	spin_lock_irqsave(&io_request_lock, flags);	rq = HWGROUP(drive)->rq;	/*	 * decide whether to reenable DMA -- 3 is a random magic for now,	 * if we DMA timeout more than 3 times, just stay in PIO	 */	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {		drive->state = 0;		HWGROUP(drive)->hwif->ide_dma_on(drive);	}	if (!end_that_request_first(rq, uptodate, drive->name)) {		add_blkdev_randomness(MAJOR(rq->rq_dev));		blkdev_dequeue_request(rq);		HWGROUP(drive)->rq = NULL;		end_that_request_last(rq);		ret = 0;	}	spin_unlock_irqrestore(&io_request_lock, flags);	return ret;}/* *	idefloppy_do_end_request is used to finish servicing a request. * *	For read/write requests, we will call ide_end_request to pass to the *	next buffer. */static int idefloppy_do_end_request (ide_drive_t *drive, int uptodate){	idefloppy_floppy_t *floppy = drive->driver_data;	struct request *rq = HWGROUP(drive)->rq;	int error;#if IDEFLOPPY_DEBUG_LOG	printk(KERN_INFO "Reached idefloppy_end_request\n");#endif /* IDEFLOPPY_DEBUG_LOG */	switch (uptodate) {		case 0: error = IDEFLOPPY_ERROR_GENERAL; break;		case 1: error = 0; break;		default: error = uptodate;	}	if (error)		floppy->failed_pc = NULL;	/* Why does this happen? */	if (!rq)		return 0;	if (!IDEFLOPPY_RQ_CMD(rq->cmd)) {		/* our real local end request function */		idefloppy_end_request(drive, uptodate);		return 0;	}	rq->errors = error;	/* fixme: need to move this local also */	ide_end_drive_cmd(drive, 0, 0);	return 0;}static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount){	struct request *rq = pc->rq;	struct buffer_head *bh = rq->bh;	int count;	while (bcount) {		if (pc->b_count == bh->b_size) {			rq->sector += rq->current_nr_sectors;			rq->nr_sectors -= rq->current_nr_sectors;			idefloppy_do_end_request(drive, 1);			if ((bh = rq->bh) != NULL)				pc->b_count = 0;		}		if (bh == NULL) {			printk(KERN_ERR "%s: bh == NULL in "				"idefloppy_input_buffers, bcount == %d\n",				drive->name, bcount);			idefloppy_discard_data(drive, bcount);			return;		}		count = IDEFLOPPY_MIN(bh->b_size - pc->b_count, bcount);		HWIF(drive)->atapi_input_bytes(drive, bh->b_data + pc->b_count, count);		bcount -= count;		pc->b_count += count;	}}static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount){	struct request *rq = pc->rq;	struct buffer_head *bh = rq->bh;	int count;		while (bcount) {		if (!pc->b_count) {			rq->sector += rq->current_nr_sectors;			rq->nr_sectors -= rq->current_nr_sectors;			idefloppy_do_end_request(drive, 1);			if ((bh = rq->bh) != NULL) {				pc->b_data = bh->b_data;				pc->b_count = bh->b_size;			}		}		if (bh == NULL) {			printk(KERN_ERR "%s: bh == NULL in "				"idefloppy_output_buffers, bcount == %d\n",				drive->name, bcount);			idefloppy_write_zeros (drive, bcount);			return;		}		count = IDEFLOPPY_MIN(pc->b_count, bcount);		HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);		bcount -= count;		pc->b_data += count;		pc->b_count -= count;	}}#ifdef CONFIG_BLK_DEV_IDEDMAstatic void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc){	struct request *rq = pc->rq;	struct buffer_head *bh = rq->bh;	while ((bh = rq->bh) != NULL)		idefloppy_do_end_request(drive, 1);}#endif /* CONFIG_BLK_DEV_IDEDMA *//* *	idefloppy_queue_pc_head generates a new packet command request in front *	of the request queue, before the current request, so that it will be *	processed immediately, on the next pass through the driver. */static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq){	ide_init_drive_cmd(rq);	rq->buffer = (char *)pc;	rq->cmd = IDEFLOPPY_PC_RQ;	(void) ide_do_drive_cmd(drive, rq, ide_preempt);}static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)		floppy->pc_stack_index=0;	return (&floppy->pc_stack[floppy->pc_stack_index++]);}static struct request *idefloppy_next_rq_storage (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK)		floppy->rq_stack_index = 0;	return (&floppy->rq_stack[floppy->rq_stack_index++]);}/* *	idefloppy_analyze_error is called on each failed packet command retry *	to analyze the request sense. */static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result){	idefloppy_floppy_t *floppy = drive->driver_data;	floppy->sense_key = result->sense_key;	floppy->asc = result->asc;	floppy->ascq = result->ascq;	floppy->progress_indication = result->sksv[0] & 0x80 ?		(u16)get_unaligned((u16 *)(result->sksv+1)):0x10000;#if IDEFLOPPY_DEBUG_LOG	if (floppy->failed_pc)		printk(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "			"asc = %x, ascq = %x\n", floppy->failed_pc->c[0],			result->sense_key, result->asc, result->ascq);	else		printk(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "			"ascq = %x\n", result->sense_key,			result->asc, result->ascq);#endif /* IDEFLOPPY_DEBUG_LOG */}static void idefloppy_request_sense_callback (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;#if IDEFLOPPY_DEBUG_LOG	printk(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);#endif /* IDEFLOPPY_DEBUG_LOG */	if (!floppy->pc->error) {		idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);		idefloppy_do_end_request(drive, 1);	} else {		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");		idefloppy_do_end_request(drive, 0);	}}/* *	General packet command callback function. */static void idefloppy_pc_callback (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	#if IDEFLOPPY_DEBUG_LOG	printk (KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);#endif /* IDEFLOPPY_DEBUG_LOG */	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1);}/* *	idefloppy_init_pc initializes a packet command. */static void idefloppy_init_pc (idefloppy_pc_t *pc){	memset(pc->c, 0, 12);	pc->retries = 0;	pc->flags = 0;	pc->request_transfer = 0;	pc->buffer = pc->pc_buffer;	pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE;	pc->b_data = NULL;	pc->callback = &idefloppy_pc_callback;}static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc){	idefloppy_init_pc(pc);		pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD;	pc->c[4] = 255;	pc->request_transfer = 18;	pc->callback = &idefloppy_request_sense_callback;}/* *	idefloppy_retry_pc is called when an error was detected during the *	last packet command. We queue a request sense packet command in *	the head of the request list. */static void idefloppy_retry_pc (ide_drive_t *drive){	idefloppy_pc_t *pc;	struct request *rq;	atapi_error_t error;	error.all = HWIF(drive)->INB(IDE_ERROR_REG);	pc = idefloppy_next_pc_storage(drive);	rq = idefloppy_next_rq_storage(drive);	idefloppy_create_request_sense_cmd(pc);	idefloppy_queue_pc_head(drive, pc, rq);}/* *	idefloppy_pc_intr is the usual interrupt handler which will be called *	during a packet command. */static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	atapi_status_t status;	atapi_bcount_t bcount;	atapi_ireason_t ireason;	idefloppy_pc_t *pc = floppy->pc;	struct request *rq = pc->rq;	unsigned int temp;#if IDEFLOPPY_DEBUG_LOG	printk(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",		__FUNCTION__);#endif /* IDEFLOPPY_DEBUG_LOG */	#ifdef CONFIG_BLK_DEV_IDEDMA	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {		if (HWIF(drive)->ide_dma_end(drive)) {			set_bit(PC_DMA_ERROR, &pc->flags);		} else {			pc->actually_transferred = pc->request_transfer;			idefloppy_update_buffers(drive, pc);		}#if IDEFLOPPY_DEBUG_LOG		printk (KERN_INFO "ide-floppy: DMA finished\n");#endif /* IDEFLOPPY_DEBUG_LOG */	}#endif /* CONFIG_BLK_DEV_IDEDMA */	/* Clear the interrupt */	status.all = HWIF(drive)->INB(IDE_STATUS_REG);	if (!status.b.drq) {			/* No more interrupts */#if IDEFLOPPY_DEBUG_LOG		printk(KERN_INFO "Packet command completed, %d bytes "			"transferred\n", pc->actually_transferred);#endif /* IDEFLOPPY_DEBUG_LOG */		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);		local_irq_enable();

⌨️ 快捷键说明

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