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

📄 ide-disk.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)			drive->special.b.recalibrate = 1;		++rq->errors;	}	return ide_stopped;}ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg){	ide_hwif_t *hwif;	struct request *rq;	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)		return ide_stopped;	hwif = HWIF(drive);	/* retry only "normal" I/O: */	switch (rq->cmd) {		case IDE_DRIVE_CMD:		case IDE_DRIVE_TASK:		case IDE_DRIVE_TASKFILE:			rq->errors = 1;			ide_end_drive_cmd(drive, BUSY_STAT, 0);			return ide_stopped;#if 0		case IDE_DRIVE_TASKFILE:			rq->errors = 1;			ide_end_taskfile(drive, BUSY_STAT, 0);			return ide_stopped;#endif		default:			break;	}	rq->errors |= ERROR_RESET;	DRIVER(drive)->end_request(drive, 0);	return ide_stopped;}/* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. */static unsigned long idedisk_read_native_max_address(ide_drive_t *drive){	ide_task_t args;	unsigned long addr = 0;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;	args.command_type			= ide_cmd_type_parser(&args);	/* submit command request */	ide_raw_taskfile(drive, &args, NULL);	/* if OK, compute maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));	}	addr++;	/* since the return value is (maxlba - 1), we add 1 */	return addr;}static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive){	ide_task_t args;	unsigned long long addr = 0;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;	args.command_type			= ide_cmd_type_parser(&args);        /* submit command request */        ide_raw_taskfile(drive, &args, NULL);	/* if OK, compute maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |  			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); 		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |			    (args.tfRegister[IDE_SECTOR_OFFSET]);		addr = ((__u64)high << 24) | low;	}	addr++;	/* since the return value is (maxlba - 1), we add 1 */	return addr;}#ifdef CONFIG_IDEDISK_STROKE/* * Sets maximum virtual LBA address of the drive. * Returns new maximum virtual LBA address (> 0) or 0 on failure. */static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req){	ide_task_t args;	unsigned long addr_set = 0;		addr_req--;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;	args.command_type			= ide_cmd_type_parser(&args);	/* submit command request */	ide_raw_taskfile(drive, &args, NULL);	/* if OK, read new maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));	}	addr_set++;	return addr_set;}static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req){	ide_task_t args;	unsigned long long addr_set = 0;	addr_req--;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;	args.hobRegister[IDE_SECTOR_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);	args.hobRegister[IDE_LCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);	args.hobRegister[IDE_HCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);	args.hobRegister[IDE_SELECT_OFFSET_HOB]	= 0x40;	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);	args.command_type			= ide_cmd_type_parser(&args);	/* submit command request */	ide_raw_taskfile(drive, &args, NULL);	/* if OK, compute maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |			    (args.tfRegister[IDE_SECTOR_OFFSET]);		addr_set = ((__u64)high << 24) | low;	}	return addr_set;}#endif /* CONFIG_IDEDISK_STROKE *//* * Tests if the drive supports Host Protected Area feature. * Returns true if supported, false otherwise. */static inline int idedisk_supports_host_protected_area(ide_drive_t *drive){	int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;	if (flag)		printk("%s: host protected area => %d\n", drive->name, flag);	return flag;}/* * Compute drive->capacity, the full capacity of the drive * Called with drive->id != NULL. * * To compute capacity, this uses either of * *    1. CHS value set by user       (whatever user sets will be trusted) *    2. LBA value from target drive (require new ATA feature) *    3. LBA value from system BIOS  (new one is OK, old one may break) *    4. CHS value from system BIOS  (traditional style) * * in above order (i.e., if value of higher priority is available, * reset will be ignored). */#define IDE_STROKE_LIMIT	(32000*1024*2)static void init_idedisk_capacity (ide_drive_t  *drive){	struct hd_driveid *id = drive->id;	unsigned long capacity = drive->cyl * drive->head * drive->sect;	unsigned long set_max = idedisk_read_native_max_address(drive);	unsigned long long capacity_2 = capacity;	unsigned long long set_max_ext;	drive->capacity48 = 0;	drive->select.b.lba = 0;	(void) idedisk_supports_host_protected_area(drive);	if (id->cfs_enable_2 & 0x0400) {		capacity_2 = id->lba_capacity_2;		drive->head		= drive->bios_head = 255;		drive->sect		= drive->bios_sect = 63;		drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);		drive->select.b.lba	= 1;		set_max_ext = idedisk_read_native_max_address_ext(drive);		if (set_max_ext > capacity_2 && capacity_2 > IDE_STROKE_LIMIT) {#ifdef CONFIG_IDEDISK_STROKE			set_max_ext = idedisk_read_native_max_address_ext(drive);			set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);			if (set_max_ext) {				drive->capacity48 = capacity_2 = set_max_ext;				drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect);				drive->select.b.lba = 1;				drive->id->lba_capacity_2 = capacity_2;                        }#else /* !CONFIG_IDEDISK_STROKE */			printk(KERN_INFO "%s: setmax_ext LBA %llu, native  %llu\n",				drive->name, set_max_ext, capacity_2);#endif /* CONFIG_IDEDISK_STROKE */		}		drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);		drive->bios_cyl		= drive->cyl;		drive->capacity48	= capacity_2;		drive->capacity		= (unsigned long) capacity_2;		return;	/* Determine capacity, and use LBA if the drive properly supports it */	} else if ((id->capability & 2) && lba_capacity_is_ok(id)) {		capacity = id->lba_capacity;		drive->cyl = capacity / (drive->head * drive->sect);		drive->select.b.lba = 1;	}	if (set_max > capacity && capacity > IDE_STROKE_LIMIT) {#ifdef CONFIG_IDEDISK_STROKE		set_max = idedisk_read_native_max_address(drive);		set_max = idedisk_set_max_address(drive, set_max);		if (set_max) {			drive->capacity = capacity = set_max;			drive->cyl = set_max / (drive->head * drive->sect);			drive->select.b.lba = 1;			drive->id->lba_capacity = capacity;		}#else /* !CONFIG_IDEDISK_STROKE */		printk(KERN_INFO "%s: setmax LBA %lu, native  %lu\n",			drive->name, set_max, capacity);#endif /* CONFIG_IDEDISK_STROKE */	}	drive->capacity = capacity;	if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {		drive->capacity48 = id->lba_capacity_2;		drive->head = 255;		drive->sect = 63;		drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect);	}}static unsigned long idedisk_capacity (ide_drive_t *drive){	if (drive->id->cfs_enable_2 & 0x0400)		return (drive->capacity48 - drive->sect0);	return (drive->capacity - drive->sect0);}static ide_startstop_t idedisk_special (ide_drive_t *drive){	special_t *s = &drive->special;	if (s->b.set_geometry) {		s->b.set_geometry	= 0;		if (!IS_PDC4030_DRIVE) {			ide_task_t args;			memset(&args, 0, sizeof(ide_task_t));			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;			args.tfRegister[IDE_SECTOR_OFFSET]  = drive->sect;			args.tfRegister[IDE_LCYL_OFFSET]    = drive->cyl;			args.tfRegister[IDE_HCYL_OFFSET]    = drive->cyl>>8;			args.tfRegister[IDE_SELECT_OFFSET]  = ((drive->head-1)|drive->select.all)&0xBF;			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;			args.command_type = ide_cmd_type_parser(&args);			do_rw_taskfile(drive, &args);		}	} else if (s->b.recalibrate) {		s->b.recalibrate = 0;		if (!IS_PDC4030_DRIVE) {			ide_task_t args;			memset(&args, 0, sizeof(ide_task_t));			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;			args.command_type = ide_cmd_type_parser(&args);			do_rw_taskfile(drive, &args);		}	} else if (s->b.set_multmode) {		s->b.set_multmode = 0;		if (drive->mult_req > drive->id->max_multsect)			drive->mult_req = drive->id->max_multsect;		if (!IS_PDC4030_DRIVE) {			ide_task_t args;			memset(&args, 0, sizeof(ide_task_t));			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;			args.command_type = ide_cmd_type_parser(&args);			do_rw_taskfile(drive, &args);		}	} else if (s->all) {		int special = s->all;		s->all = 0;		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);		return ide_stopped;	}	return IS_PDC4030_DRIVE ? ide_stopped : ide_started;}static void idedisk_pre_reset (ide_drive_t *drive){	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;	drive->special.all = 0;	drive->special.b.set_geometry = legacy;	drive->special.b.recalibrate  = legacy;	if (OK_TO_RESET_CONTROLLER)		drive->mult_count = 0;	if (!drive->keep_settings && !drive->using_dma)		drive->mult_req = 0;	if (drive->mult_req != drive->mult_count)		drive->special.b.set_multmode = 1;}#ifdef CONFIG_PROC_FSstatic int smart_enable(ide_drive_t *drive){	ide_task_t args;	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_FEATURE_OFFSET]	= SMART_ENABLE;	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;	args.command_type			= ide_cmd_type_parser(&args);	return ide_raw_taskfile(drive, &args, NULL);}static int get_smart_values(ide_drive_t *drive, u8 *buf){	ide_task_t args;	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_FEATURE_OFFSET]	= SMART_READ_VALUES;	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;	args.command_type			= ide_cmd_type_parser(&args);	(void) smart_enable(drive);	return ide_raw_taskfile(drive, &args, buf);}static int get_smart_thresholds(ide_drive_t *drive, u8 *buf){	ide_task_t args;	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_FEATURE_OFFSET]	= SMART_READ_THRESHOLDS;	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;	args.command_type			= ide_cmd_type_parser(&args);	(void) smart_enable(drive);	return ide_raw_taskfile(drive, &args, buf);}static int proc_idedisk_read_cache	(char *page, char **start, off_t off, int count, int *eof, void *data){	ide_drive_t	*drive = (ide_drive_t *) data;	char		*out = page;	int		len;	if (drive->id_read)		len = sprintf(out,"%i\n", drive->id->buf_size / 2);	else		len = sprintf(out,"(none)\n");	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);}static int proc_idedisk_read_smart_thresholds	(char *page, char **start, off_t off, int count, int *eof, void *data){	ide_drive_t	*drive = (ide_drive_t *)data;	int		len = 0, i = 0;	if (!get_smart_thresholds(drive, page)) {		unsigned short *val = (unsigned short *) page;		char *out = ((char *)val) + (SECTOR_WORDS * 4);		page = out;		do {			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');			val += 1;		} while (i < (SECTOR_WORDS * 2));		len = out - page;	}	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);}static int proc_idedisk_read_smart_values	(char *page, char **start, off_t off, int count, int *eof, void *data){	ide_drive_t	*drive = (ide_drive_t *)data;	int		len = 0, i = 0;	if (!get_smart_values(drive, page)) {		unsigned short *val = (unsigned short *) page;		char *out = ((char *)val) + (SECTOR_WORDS * 4);		page = out;		do {			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');			val += 1;		} while (i < (SECTOR_WORDS * 2));		len = out - page;	}	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);}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 *//* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. */static int set_multcount(ide_drive_t *drive, int arg){	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);	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){	ide_task_t args;	if (!(drive->id->cfs_enable_2 & 0x3000))		return 1;	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ?			SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;

⌨️ 快捷键说明

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