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

📄 ide-floppy.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef CONFIG_BLK_DEV_IDEDMA	if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {		if (HWIF(drive)->dmaproc(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 */	status.all = GET_STAT();					/* Clear the interrupt */	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);		ide__sti();	/* local CPU only */		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);			}			idefloppy_retry_pc (drive);				/* Retry operation */			return ide_stopped; /* queued, but not started */		}		pc->error = 0;		if (floppy->failed_pc == pc)			floppy->failed_pc=NULL;		pc->callback(drive);			/* Command finished - Call the callback function */		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)->dmaproc(ide_dma_off, drive);		return ide_do_reset (drive);	}#endif /* CONFIG_BLK_DEV_IDEDMA */	bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG);			/* Get the number of bytes to transfer */	bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG);			/* on this interrupt */	ireason.all=IN_BYTE (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);				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)			atapi_output_bytes (drive,pc->current_position,bcount.all);	/* Write the current buffer */		else			idefloppy_output_buffers (drive, pc, bcount.all);	} else {		if (pc->buffer != NULL)			atapi_input_bytes (drive,pc->current_position,bcount.all);	/* Read the current buffer */		else			idefloppy_input_buffers (drive, pc, bcount.all);	}	pc->actually_transferred+=bcount.all;				/* Update the current position */	pc->current_position+=bcount.all;	ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */	return ide_started;}static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive){	ide_startstop_t startstop;	idefloppy_floppy_t *floppy = drive->driver_data;	idefloppy_ireason_reg_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=IN_BYTE (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);	}	ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);	/* Set the interrupt routine */	atapi_output_bytes (drive, floppy->pc->c, 12);		/* Send the actual packet */	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;	idefloppy_bcount_reg_t bcount;	int dma_ok = 0;#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;	floppy->pc=pc;							/* Set the current packet command */	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)) {			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);			pc->error = IDEFLOPPY_ERROR_GENERAL;		/* Giving up */		}		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++;	pc->actually_transferred=0;					/* We haven't transferred any data yet */	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)->dmaproc(ide_dma_off, drive);	}	if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);#endif /* CONFIG_BLK_DEV_IDEDMA */	if (IDE_CONTROL_REG)		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);	OUT_BYTE (drive->select.all,IDE_SELECT_REG);#ifdef CONFIG_BLK_DEV_IDEDMA	if (dma_ok) {							/* Begin DMA, if necessary */		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));	}#endif /* CONFIG_BLK_DEV_IDEDMA */	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {		ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD, NULL);		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */		return ide_started;	} else {		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		return idefloppy_transfer_pc (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_end_request(1, HWGROUP(drive));	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;}/* *	A mode sense command is used to "sense" floppy parameters. */static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, byte page_code, byte type){	unsigned short 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), (unsigned short *) &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), (unsigned short *) &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;	pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;	set_bit (PC_DMA_RECOMMENDED, &pc->flags);}/* *	idefloppy_do_request is our request handling function.	 */static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block){	idefloppy_floppy_t *floppy = drive->driver_data;	idefloppy_pc_t *pc;#if IDEFLOPPY_DEBUG_LOG	printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);#endif /* IDEFLOPPY_DEBUG_LOG */	if (rq->errors >= ERROR_MAX) {		if (floppy->failed_pc != NULL)			printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",				drive->name, floppy->failed_pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq);		else			printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name);		idefloppy_end_request (0, HWGROUP(drive));		return ide_stopped;	}	switch (rq->cmd) {		case READ:		case WRITE:			if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) {				printk ("%s: unsupported r/w request size\n", drive->name);				idefloppy_end_request (0, HWGROUP(drive));				return ide_stopped;			}			pc = idefloppy_next_pc_storage (drive);			idefloppy_create_rw_cmd (floppy, pc, rq, block);			break;		case IDEFLOPPY_PC_RQ:			pc = (idefloppy_pc_t *) rq->buffer;			break;		default:			printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd);			idefloppy_end_request (0,HWGROUP (drive));			return ide_stopped;	}	pc->rq = rq;	return idefloppy_issue_pc (drive, pc);}/* *	idefloppy_queue_pc_tail adds a special packet command request to the *	tail of the request queue, and waits for it to be serviced. */static int idefloppy_queue_pc_tail (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;	return ide_do_drive_cmd (drive, &rq, ide_wait);}/* *	Look at the flexible disk page parameters. We will ignore the CHS *	capacity parameters and use the LBA parameters instead. */static int idefloppy_get_flexible_disk_page (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	idefloppy_pc_t pc;	idefloppy_mode_parameter_header_t *header;	idefloppy_flexible_disk_page_t *page;	int capacity, lba_capacity;	idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT);	if (idefloppy_queue_pc_tail (drive,&pc)) {		printk (KERN_ERR "ide-floppy: Can't get flexible disk page parameters\n");		return 1;	}	header = (idefloppy_mode_parameter_header_t *) pc.buffer;	floppy->wp = header->wp;	page = (idefloppy_flexible_disk_page_t *) (header + 1);	page->transfer_rate = ntohs (page->transfer_rate);	page->sector_size = ntohs (page->sector_size);	page->cyls = ntohs (page->cyls);	page->rpm = ntohs (page->rpm);	capacity = page->cyls * page->heads * page->sectors * page->sector_size;	if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t)))		printk (KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, %d sector size, %d rpm\n",			drive->name, capacity / 1024, page->cyls, page->heads, page->sectors,			page->transfer_rate / 8, page->sector_size, page->rpm);	floppy->flexible_disk_page = *page;	drive->bios_cyl = page->cyls;	drive->bios_head = page->heads;	drive->bios_sect = page->sectors;	lba_capacity = floppy->blocks * floppy->block_size;	if (capacity < lba_capacity) {		printk (KERN_NOTICE "%s: The disk reports a capacity of %d bytes, "			"but the drive only handles %d\n",			drive->name, lba_capacity, capacity);		floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0;	}	return 0;}/* *	Determine if a media is present in the floppy drive, and if so, *	its LBA capacity. */static int idefloppy_get_capacity (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	idefloppy_pc_t pc;	idefloppy_capacity_header_t *header;	idefloppy_capacity_descriptor_t *descriptor;	int i, descriptors, rc = 1, blocks, length;		drive->bios_cyl = 0;	drive->bios_head = drive->bios_sect = 0;	floppy->blocks = floppy->bs_factor = 0;	drive->part[0].nr_sects = 0;	idefloppy_create_read_capacity_cmd (&pc);	if (idefloppy_queue_pc_tail (drive, &pc)) {		printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n");		return 1;	}	header = (idefloppy_capacity_header_t *) pc.buffer;	descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t);	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);	for (i = 0; i < descriptors; i++, descriptor++) {		blocks = descriptor->blocks = ntohl (descriptor->blocks);		length = descriptor->length = ntohs (descriptor->length);		if (!i && descriptor->dc == CAPACITY_CURRENT) {			if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) {				printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n",					drive->name, blocks * length / 1024, blocks, length,

⌨️ 快捷键说明

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