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

📄 ide-disk.c

📁 2410的硬盘块设备源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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]	= (addr_req >>= 8) & 0xff;	args.hobRegister[IDE_LCYL_OFFSET]	= (addr_req >>= 8) & 0xff;	args.hobRegister[IDE_HCYL_OFFSET]	= (addr_req >>= 8) & 0xff;	args.hobRegister[IDE_SELECT_OFFSET]	= 0x40;	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	/* 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] << 16) |			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |			    args.hobRegister[IDE_SECTOR_OFFSET];		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;		addr_set++;	}	return addr_set;}static unsigned long long sectors_to_MB(unsigned long long n){	n <<= 9;		/* make it bytes */	do_div(n, 1000000);	/* make it MB */	return n;}/* * Bits 10 of command_set_1 and cfs_enable_1 must be equal, * so on non-buggy drives we need test only one. * However, we should also check whether these fields are valid. */static inline int idedisk_supports_hpa(const struct hd_driveid *id){	return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);}/* * The same here. */static inline int idedisk_supports_lba48(const struct hd_driveid *id){	return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)	       && id->lba_capacity_2;}static inline void idedisk_check_hpa(ide_drive_t *drive){	unsigned long long capacity, set_max;	int lba48 = idedisk_supports_lba48(drive->id);	capacity = drive->capacity64;	if (lba48)		set_max = idedisk_read_native_max_address_ext(drive);	else		set_max = idedisk_read_native_max_address(drive);	if (set_max <= capacity)		return;	printk(KERN_INFO "%s: Host Protected Area detected.\n"			 "\tcurrent capacity is %llu sectors (%llu MB)\n"			 "\tnative  capacity is %llu sectors (%llu MB)\n",			 drive->name,			 capacity, sectors_to_MB(capacity),			 set_max, sectors_to_MB(set_max));	if (lba48)		set_max = idedisk_set_max_address_ext(drive, set_max);	else		set_max = idedisk_set_max_address(drive, set_max);	if (set_max) {		drive->capacity64 = set_max;		printk(KERN_INFO "%s: Host Protected Area disabled.\n",				 drive->name);	}}/* * 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). */static void init_idedisk_capacity (ide_drive_t  *drive){	struct hd_driveid *id = drive->id;	/*	 * If this drive supports the Host Protected Area feature set,	 * then we may need to change our opinion about the drive's capacity.	 */	int hpa = idedisk_supports_hpa(id);	if (idedisk_supports_lba48(id)) {		/* drive speaks 48-bit LBA */		drive->select.b.lba = 1;		drive->capacity64 = id->lba_capacity_2;		if (hpa)			idedisk_check_hpa(drive);	} else if ((id->capability & 2) && lba_capacity_is_ok(id)) {		/* drive speaks 28-bit LBA */		drive->select.b.lba = 1;		drive->capacity64 = id->lba_capacity;		if (hpa)			idedisk_check_hpa(drive);	} else {		/* drive speaks boring old 28-bit CHS */		drive->capacity64 = drive->cyl * drive->head * drive->sect;	}}static sector_t idedisk_capacity (ide_drive_t *drive){	return drive->capacity64 - drive->sect0;}#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_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	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_DRIVE_TASK_IN;	args.data_phase				= TASKFILE_IN;	args.handler				= &task_in_intr;	(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_DRIVE_TASK_IN;	args.data_phase				= TASKFILE_IN;	args.handler				= &task_in_intr;	(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_capacity	(char *page, char **start, off_t off, int count, int *eof, void *data){	ide_drive_t*drive = (ide_drive_t *)data;	int len;	len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));	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 },	{ "capacity",		S_IFREG|S_IRUGO,	proc_idedisk_read_capacity,		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 void idedisk_end_flush(request_queue_t *q, struct request *flush_rq){	ide_drive_t *drive = q->queuedata;	struct request *rq = flush_rq->end_io_data;	int good_sectors = rq->hard_nr_sectors;	int bad_sectors;	sector_t sector;	if (flush_rq->errors & ABRT_ERR) {		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);		blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);		blk_queue_issue_flush_fn(drive->queue, NULL);		good_sectors = 0;	} else if (flush_rq->errors) {		good_sectors = 0;		if (blk_barrier_preflush(rq)) {			sector = ide_get_error_location(drive,flush_rq->buffer);			if ((sector >= rq->hard_sector) &&			    (sector < rq->hard_sector + rq->hard_nr_sectors))				good_sectors = sector - rq->hard_sector;		}	}	if (flush_rq->errors)		printk(KERN_ERR "%s: failed barrier write: "				"sector=%Lx(good=%d/bad=%d)\n",				drive->name, (unsigned long long)rq->sector,				good_sectors,				(int) (rq->hard_nr_sectors-good_sectors));	bad_sectors = rq->hard_nr_sectors - good_sectors;	if (good_sectors)		__ide_end_request(drive, rq, 1, good_sectors);	if (bad_sectors)		__ide_end_request(drive, rq, 0, bad_sectors);}static int idedisk_prepare_flush(request_queue_t *q, struct request *rq){	ide_drive_t *drive = q->queuedata;	if (!drive->wcache)		return 0;	memset(rq->cmd, 0, sizeof(rq->cmd));	if (ide_id_has_flush_cache_ext(drive->id) &&	    (drive->capacity64 >= (1UL << 28)))		rq->cmd[0] = WIN_FLUSH_CACHE_EXT;	else		rq->cmd[0] = WIN_FLUSH_CACHE;	rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;	rq->buffer = rq->cmd;	return 1;}static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,			       sector_t *error_sector){	ide_drive_t *drive = q->queuedata;	struct request *rq;	int ret;	if (!drive->wcache)		return 0;	rq = blk_get_request(q, WRITE, __GFP_WAIT);	idedisk_prepare_flush(q, rq);	ret = blk_execute_rq(q, disk, rq, 0);	/*	 * if we failed and caller wants error offset, get it	 */	if (ret && error_sector)		*error_sector = ide_get_error_location(drive, rq->cmd);	blk_put_request(rq);	return ret;}/* * 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.flags = REQ_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(&ide_lock);	return 0;}static int write_cache(ide_drive_t *drive, int arg){	ide_task_t args;	int err;	if (!ide_id_has_flush_cache(drive->id))		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;	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	err = ide_raw_taskfile(drive, &args, NULL);	if (err)		return err;	drive->wcache = arg;	return 0;}static int do_idedisk_flushcache (ide_drive_t *drive){	ide_task_t args;	memset(&args, 0, sizeof(ide_task_t));	if (ide_id_has_flush_cache_ext(drive->id))		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE_EXT;	else		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE;	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	return ide_raw_taskfile(drive, &args, NULL);}static int set_acoustic (ide_drive_t *drive, int arg){	ide_task_t args;	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ? SETFEATURES_EN_AAM :							  SETFEATURES_DIS_AAM;	args.tfRegister[IDE_NSECTOR_OFFSET]	= arg;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;	args.command_type = IDE_DRIVE_TASK_NO_DATA;	args.handler	  = &task_no_data_intr;	ide_raw_taskfile(drive, &args, NULL);	drive->acoustic = arg;	return 0;}/* * drive->addressing: *	0: 28-bit *	1: 48-bit *	2: 48-bit capable doing 28-bit

⌨️ 快捷键说明

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