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

📄 ide-floppy.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
};/* *	INQUIRY packet command - Data Format */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD)	unsigned	device_type	:5;	/* Peripheral Device Type */	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */	unsigned	reserved1_6t0	:7;	/* Reserved */	unsigned	rmb		:1;	/* Removable Medium Bit */	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;static DEFINE_MUTEX(idefloppy_ref_mutex);#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)#define ide_floppy_g(disk) \	container_of((disk)->private_data, struct ide_floppy_obj, driver)static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk){	struct ide_floppy_obj *floppy = NULL;	mutex_lock(&idefloppy_ref_mutex);	floppy = ide_floppy_g(disk);	if (floppy)		kref_get(&floppy->kref);	mutex_unlock(&idefloppy_ref_mutex);	return floppy;}static void ide_floppy_release(struct kref *);static void ide_floppy_put(struct ide_floppy_obj *floppy){	mutex_lock(&idefloppy_ref_mutex);	kref_put(&floppy->kref, ide_floppy_release);	mutex_unlock(&idefloppy_ref_mutex);}/* *	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 *//* *	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, int nsecs){	idefloppy_floppy_t *floppy = drive->driver_data;	struct request *rq = HWGROUP(drive)->rq;	int error;	debug_log(KERN_INFO "Reached idefloppy_end_request\n");	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 (!blk_special_request(rq)) {		/* our real local end request function */		ide_end_request(drive, uptodate, nsecs);		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 bio_vec *bvec;	struct req_iterator iter;	unsigned long flags;	char *data;	int count, done = 0;	rq_for_each_segment(bvec, rq, iter) {		if (!bcount)			break;		count = min(bvec->bv_len, bcount);		data = bvec_kmap_irq(bvec, &flags);		drive->hwif->atapi_input_bytes(drive, data, count);		bvec_kunmap_irq(data, &flags);		bcount -= count;		pc->b_count += count;		done += count;	}	idefloppy_do_end_request(drive, 1, done >> 9);	if (bcount) {		printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);		idefloppy_discard_data(drive, bcount);	}}static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount){	struct request *rq = pc->rq;	struct req_iterator iter;	struct bio_vec *bvec;	unsigned long flags;	int count, done = 0;	char *data;	rq_for_each_segment(bvec, rq, iter) {		if (!bcount)			break;		count = min(bvec->bv_len, bcount);		data = bvec_kmap_irq(bvec, &flags);		drive->hwif->atapi_output_bytes(drive, data, count);		bvec_kunmap_irq(data, &flags);		bcount -= count;		pc->b_count += count;		done += count;	}	idefloppy_do_end_request(drive, 1, done >> 9);#if IDEFLOPPY_DEBUG_BUGS	if (bcount) {		printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);		idefloppy_write_zeros(drive, bcount);	}#endif}static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc){	struct request *rq = pc->rq;	struct bio *bio = rq->bio;	while ((bio = rq->bio) != NULL)		idefloppy_do_end_request(drive, 1, 0);}/* *	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){	struct ide_floppy_obj *floppy = drive->driver_data;	ide_init_drive_cmd(rq);	rq->buffer = (char *) pc;	rq->cmd_type = REQ_TYPE_SPECIAL;	rq->rq_disk = floppy->disk;	(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 (floppy->failed_pc)		debug_log(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		debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "			"ascq = %x\n", result->sense_key,			result->asc, result->ascq);}static void idefloppy_request_sense_callback (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);		if (!floppy->pc->error) {		idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);		idefloppy_do_end_request(drive, 1, 0);	} else {		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");		idefloppy_do_end_request(drive, 0, 0);	}}/* *	General packet command callback function. */static void idefloppy_pc_callback (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;		debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);}/* *	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->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;	debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",		__FUNCTION__);	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);		}		debug_log(KERN_INFO "ide-floppy: DMA finished\n");	}	/* Clear the interrupt */	status.all = HWIF(drive)->INB(IDE_STATUS_REG);	if (!status.b.drq) {			/* No more interrupts */		debug_log(KERN_INFO "Packet command completed, %d bytes "			"transferred\n", pc->actually_transferred);		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);		local_irq_enable_in_hardirq();		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {			/* Error detected */			debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",

⌨️ 快捷键说明

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