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

📄 ide-disk.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return addr;	/* 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.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) {		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.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_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.handler				= task_no_data_intr;	/* 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.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_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;}/* * 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;	printk("%s: host protected area => %d\n", drive->name, flag);	return flag;}#endif /* CONFIG_IDEDISK_STROKE *//* * 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;	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;	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) {#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("%s: setmax_ext LBA %llu, native  %llu\n",				drive->name, set_max_ext, capacity_2);#endif /* CONFIG_IDEDISK_STROKE */		}		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) {#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("%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) {		struct hd_drive_task_hdr taskfile;		struct hd_drive_hob_hdr hobfile;		ide_handler_t *handler = NULL;		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));		s->b.set_geometry	= 0;		taskfile.sector_number	= drive->sect;		taskfile.low_cylinder	= drive->cyl;		taskfile.high_cylinder	= drive->cyl>>8;		taskfile.device_head	= ((drive->head-1)|drive->select.all)&0xBF;		if (!IS_PDC4030_DRIVE) {			taskfile.sector_count	= drive->sect;			taskfile.command	= WIN_SPECIFY;			handler			= ide_handler_parser(&taskfile, &hobfile);		}		do_taskfile(drive, &taskfile, &hobfile, handler);	} else if (s->b.recalibrate) {		s->b.recalibrate = 0;		if (!IS_PDC4030_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.sector_count	= drive->sect;			taskfile.command	= WIN_RESTORE;			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));		}	} else if (s->b.set_multmode) {		s->b.set_multmode = 0;		if (drive->id && drive->mult_req > drive->id->max_multsect)			drive->mult_req = drive->id->max_multsect;		if (!IS_PDC4030_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.sector_count	= drive->mult_req;			taskfile.command	= WIN_SETMULT;			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));		}	} 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){	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	= SMART_ENABLE;	taskfile.low_cylinder	= SMART_LCYL_PASS;	taskfile.high_cylinder	= SMART_HCYL_PASS;	taskfile.command	= WIN_SMART;	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);}static int get_smart_values(ide_drive_t *drive, byte *buf){	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	= SMART_READ_VALUES;	taskfile.sector_count	= 0x01;	taskfile.low_cylinder	= SMART_LCYL_PASS;	taskfile.high_cylinder	= SMART_HCYL_PASS;	taskfile.command	= WIN_SMART;	(void) smart_enable(drive);	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);}static int get_smart_thresholds(ide_drive_t *drive, byte *buf){	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	= SMART_READ_THRESHOLDS;	taskfile.sector_count	= 0x01;	taskfile.low_cylinder	= SMART_LCYL_PASS;	taskfile.high_cylinder	= SMART_HCYL_PASS;	taskfile.command	= WIN_SMART;	(void) smart_enable(drive);	return ide_wait_taskfile(drive, &taskfile, &hobfile, 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)		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);

⌨️ 快捷键说明

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