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

📄 ide-disk.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
}static ide_proc_entry_t idedisk_proc[] = {	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },	{ NULL, 0, NULL, NULL }};#else#define	idedisk_proc	NULL#endif	/* CONFIG_PROC_FS */static int set_multcount(ide_drive_t *drive, int arg){#ifdef __TASKFILE__IO	struct hd_drive_task_hdr taskfile;	struct hd_drive_hob_hdr hobfile;	if (drive->special.b.set_multmode)		return -EBUSY;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));	taskfile.sector_count	= drive->mult_req;	taskfile.command	= WIN_SETMULT;	drive->mult_req		= arg;	drive->special.b.set_multmode = 1;	ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);#else /* !__TASKFILE__IO */	struct request rq;	if (drive->special.b.set_multmode)		return -EBUSY;	ide_init_drive_cmd (&rq);	rq.cmd = IDE_DRIVE_CMD;	drive->mult_req = arg;	drive->special.b.set_multmode = 1;	(void) ide_do_drive_cmd (drive, &rq, ide_wait);#endif /* __TASKFILE__IO */	return (drive->mult_count == arg) ? 0 : -EIO;}static int set_nowerr(ide_drive_t *drive, int arg){	if (ide_spin_wait_hwgroup(drive))		return -EBUSY;	drive->nowerr = arg;	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;	spin_unlock_irq(&io_request_lock);	return 0;}static int write_cache (ide_drive_t *drive, int arg){	struct hd_drive_task_hdr taskfile;	struct hd_drive_hob_hdr hobfile;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));	taskfile.feature	= (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;	taskfile.command	= WIN_SETFEATURES;	if (!(drive->id->cfs_enable_2 & 0x3000))		return 1;	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);	drive->wcache = arg;	return 0;}static int do_idedisk_standby (ide_drive_t *drive){	struct hd_drive_task_hdr taskfile;	struct hd_drive_hob_hdr hobfile;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));	taskfile.command	= WIN_STANDBYNOW1;	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);}static int do_idedisk_flushcache (ide_drive_t *drive){	struct hd_drive_task_hdr taskfile;	struct hd_drive_hob_hdr hobfile;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));	if (drive->id->cfs_enable_2 & 0x2400) {		taskfile.command	= WIN_FLUSH_CACHE_EXT;	} else {		taskfile.command	= WIN_FLUSH_CACHE;	}	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);}static int set_acoustic (ide_drive_t *drive, int arg){	struct hd_drive_task_hdr taskfile;	struct hd_drive_hob_hdr hobfile;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));	taskfile.feature	= (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;	taskfile.sector_count	= arg;	taskfile.command	= WIN_SETFEATURES;	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);	drive->acoustic = arg;	return 0;}static int probe_lba_addressing (ide_drive_t *drive, int arg){	drive->addressing =  0;	if (!(drive->id->cfs_enable_2 & 0x0400))                return -EIO;	drive->addressing = arg;	return 0;}static int set_lba_addressing (ide_drive_t *drive, int arg){	return (probe_lba_addressing(drive, arg));}static void idedisk_add_settings(ide_drive_t *drive){	struct hd_driveid *id = drive->id;	int major = HWIF(drive)->major;	int minor = drive->select.b.unit << PARTN_BITS;	ide_add_setting(drive,	"bios_cyl",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->bios_cyl,		NULL);	ide_add_setting(drive,	"bios_head",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	255,				1,	1,	&drive->bios_head,		NULL);	ide_add_setting(drive,	"bios_sect",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	63,				1,	1,	&drive->bios_sect,		NULL);	ide_add_setting(drive,	"address",		SETTING_RW,					HDIO_GET_ADDRESS,	HDIO_SET_ADDRESS,	TYPE_INTA,	0,	2,				1,	1,	&drive->addressing,	set_lba_addressing);	ide_add_setting(drive,	"bswap",		SETTING_READ,					-1,			-1,			TYPE_BYTE,	0,	1,				1,	1,	&drive->bswap,			NULL);	ide_add_setting(drive,	"multcount",		id ? SETTING_RW : SETTING_READ,			HDIO_GET_MULTCOUNT,	HDIO_SET_MULTCOUNT,	TYPE_BYTE,	0,	id ? id->max_multsect : 0,	1,	1,	&drive->mult_count,		set_multcount);	ide_add_setting(drive,	"nowerr",		SETTING_RW,					HDIO_GET_NOWERR,	HDIO_SET_NOWERR,	TYPE_BYTE,	0,	1,				1,	1,	&drive->nowerr,			set_nowerr);	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	1,	&read_ahead[major],		NULL);	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	4096,			PAGE_SIZE,	1024,	&max_readahead[major][minor],	NULL);	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	1,	&max_sectors[major][minor],	NULL);	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);	ide_add_setting(drive,	"wcache",		SETTING_RW,					HDIO_GET_WCACHE,	HDIO_SET_WCACHE,	TYPE_BYTE,	0,	1,				1,	1,	&drive->wcache,			write_cache);	ide_add_setting(drive,	"acoustic",		SETTING_RW,					HDIO_GET_ACOUSTIC,	HDIO_SET_ACOUSTIC,	TYPE_BYTE,	0,	254,				1,	1,	&drive->acoustic,		set_acoustic); 	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL); 	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);}static void idedisk_setup (ide_drive_t *drive){	int i;		struct hd_driveid *id = drive->id;	unsigned long capacity;		idedisk_add_settings(drive);	if (id == NULL)		return;	/*	 * CompactFlash cards and their brethern look just like hard drives	 * to us, but they are removable and don't have a doorlock mechanism.	 */	if (drive->removable && !drive_is_flashcard(drive)) {		/*		 * Removable disks (eg. SYQUEST); ignore 'WD' drives 		 */		if (id->model[0] != 'W' || id->model[1] != 'D') {			drive->doorlocking = 1;		}	}	for (i = 0; i < MAX_DRIVES; ++i) {		ide_hwif_t *hwif = HWIF(drive);		if (drive != &hwif->drives[i]) continue;		hwif->gd->de_arr[i] = drive->de;		if (drive->removable)			hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;		break;	}	/* Extract geometry if we did not already have one for the drive */	if (!drive->cyl || !drive->head || !drive->sect) {		drive->cyl     = drive->bios_cyl  = id->cyls;		drive->head    = drive->bios_head = id->heads;		drive->sect    = drive->bios_sect = id->sectors;	}	/* Handle logical geometry translation by the drive */	if ((id->field_valid & 1) && id->cur_cyls &&	    id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {		drive->cyl  = id->cur_cyls;		drive->head = id->cur_heads;		drive->sect = id->cur_sectors;	}	/* Use physical geometry if what we have still makes no sense */	if (drive->head > 16 && id->heads && id->heads <= 16) {		drive->cyl  = id->cyls;		drive->head = id->heads;		drive->sect = id->sectors;	}	/* calculate drive capacity, and select LBA if possible */	init_idedisk_capacity (drive);	/*	 * if possible, give fdisk access to more of the drive,	 * by correcting bios_cyls:	 */	capacity = idedisk_capacity (drive);	if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head)		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;	printk (KERN_INFO "%s: %ld sectors", drive->name, capacity);	/* Give size in megabytes (MB), not mebibytes (MiB). */	/* We compute the exact rounded value, avoiding overflow. */	printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950);	/* Only print cache size when it was specified */	if (id->buf_size)		printk (" w/%dKiB Cache", id->buf_size/2);	printk(", CHS=%d/%d/%d", 	       drive->bios_cyl, drive->bios_head, drive->bios_sect);#ifdef CONFIG_BLK_DEV_IDEDMA	if (drive->using_dma)		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);#endif /* CONFIG_BLK_DEV_IDEDMA */	printk("\n");	drive->mult_count = 0;	if (id->max_multsect) {#ifdef CONFIG_IDEDISK_MULTI_MODE		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;		id->multsect_valid = id->multsect ? 1 : 0;		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;#else	/* original, pre IDE-NFG, per request of AC */		drive->mult_req = INITIAL_MULT_COUNT;		if (drive->mult_req > id->max_multsect)			drive->mult_req = id->max_multsect;		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))			drive->special.b.set_multmode = 1;#endif	/* CONFIG_IDEDISK_MULTI_MODE */	}	drive->no_io_32bit = id->dword_io ? 1 : 0;	if (drive->id->cfs_enable_2 & 0x3000)		write_cache(drive, (id->cfs_enable_2 & 0x3000));	(void) probe_lba_addressing(drive, 1);}static int idedisk_cleanup (ide_drive_t *drive){	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)		if (do_idedisk_flushcache(drive))			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",				drive->name);	return ide_unregister_subdriver(drive);}int idedisk_reinit(ide_drive_t *drive);/* *      IDE subdriver functions, registered with ide.c */static ide_driver_t idedisk_driver = {	name:			"ide-disk",	version:		IDEDISK_VERSION,	media:			ide_disk,	busy:			0,	supports_dma:		1,	supports_dsc_overlap:	0,	cleanup:		idedisk_cleanup,	standby:		do_idedisk_standby,	flushcache:		do_idedisk_flushcache,	do_request:		do_rw_disk,	end_request:		NULL,	ioctl:			NULL,	open:			idedisk_open,	release:		idedisk_release,	media_change:		idedisk_media_change,	revalidate:		idedisk_revalidate,	pre_reset:		idedisk_pre_reset,	capacity:		idedisk_capacity,	special:		idedisk_special,	proc:			idedisk_proc,	reinit:			idedisk_reinit,	ata_prebuilder:		NULL,	atapi_prebuilder:	NULL,};int idedisk_init (void);static ide_module_t idedisk_module = {	IDE_DRIVER_MODULE,	idedisk_init,	&idedisk_driver,	NULL};MODULE_DESCRIPTION("ATA DISK Driver");int idedisk_reinit (ide_drive_t *drive){	int failed = 0;	MOD_INC_USE_COUNT;	if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {		printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);		return 1;	}	DRIVER(drive)->busy++;	idedisk_setup(drive);	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);		(void) idedisk_cleanup(drive);		DRIVER(drive)->busy--;		return 1;	}	DRIVER(drive)->busy--;	failed--;	ide_register_module(&idedisk_module);	MOD_DEC_USE_COUNT;	return 0;}static void __exit idedisk_exit (void){	ide_drive_t *drive;	int failed = 0;	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {		if (idedisk_cleanup (drive)) {			printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);			failed++;		}		/* We must remove proc entries defined in this module.		   Otherwise we oops while accessing these entries */#ifdef CONFIG_PROC_FS		if (drive->proc)			ide_remove_proc_entries(drive->proc, idedisk_proc);#endif	}	ide_unregister_module(&idedisk_module);}int idedisk_init (void){	ide_drive_t *drive;	int failed = 0;		MOD_INC_USE_COUNT;	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {		if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {			printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);			continue;		}		DRIVER(drive)->busy++;		idedisk_setup(drive);		if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {			printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);			(void) idedisk_cleanup(drive);			DRIVER(drive)->busy--;			continue;		}		DRIVER(drive)->busy--;		failed--;	}	ide_register_module(&idedisk_module);	MOD_DEC_USE_COUNT;	return 0;}module_init(idedisk_init);module_exit(idedisk_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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