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

📄 ide-disk.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * of data to be written.  If we hit an error (corrupted buffer list)			 * in ide_multwrite(), then we need to remove the handler/timer			 * before returning.  Fortunately, this NEVER happens (right?).			 *			 * Except when you get an error it seems...			 */			hwgroup->wrq = *rq; /* scratchpad */			ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);			if (ide_multwrite(drive, drive->mult_count)) {				unsigned long flags;				spin_lock_irqsave(&io_request_lock, flags);				hwgroup->handler = NULL;				del_timer(&hwgroup->timer);				spin_unlock_irqrestore(&io_request_lock, flags);				return ide_stopped;			}		} else {			ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);			idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);		}		return ide_started;	}	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);	ide_end_request(0, HWGROUP(drive));	return ide_stopped;}static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive){	MOD_INC_USE_COUNT;	if (drive->removable && drive->usage == 1) {		check_disk_change(inode->i_rdev);		/*		 * Ignore the return code from door_lock,		 * since the open() has already succeeded,		 * and the door_lock is irrelevant at this point.		 */		if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL))			drive->doorlocking = 0;	}	return 0;}static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive){	if (drive->removable && !drive->usage) {		invalidate_buffers(inode->i_rdev);		if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))			drive->doorlocking = 0;	}	MOD_DEC_USE_COUNT;}static int idedisk_media_change (ide_drive_t *drive){	return drive->removable;	/* if removable, always assume it was changed */}static void idedisk_revalidate (ide_drive_t *drive){	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,			1<<PARTN_BITS,			current_capacity(drive));}/* * Compute drive->capacity, the full capacity of the drive * Called with drive->id != NULL. */static void init_idedisk_capacity (ide_drive_t  *drive){	struct hd_driveid *id = drive->id;	unsigned long capacity = drive->cyl * drive->head * drive->sect;	drive->select.b.lba = 0;	/* Determine capacity, and use LBA if the drive properly supports it */	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;	}	drive->capacity = capacity;}static unsigned long idedisk_capacity (ide_drive_t  *drive){	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;		OUT_BYTE(drive->sect,IDE_SECTOR_REG);		OUT_BYTE(drive->cyl,IDE_LCYL_REG);		OUT_BYTE(drive->cyl>>8,IDE_HCYL_REG);		OUT_BYTE(((drive->head-1)|drive->select.all)&0xBF,IDE_SELECT_REG);		if (!IS_PDC4030_DRIVE)			ide_cmd(drive, WIN_SPECIFY, drive->sect, &set_geometry_intr);	} else if (s->b.recalibrate) {		s->b.recalibrate = 0;		if (!IS_PDC4030_DRIVE)			ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr);	} 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)			ide_cmd(drive, WIN_SETMULT, drive->mult_req, &set_multmode_intr);	} 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){	drive->special.all = 0;	drive->special.b.set_geometry = 1;	drive->special.b.recalibrate  = 1;	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){	return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL);}static int get_smart_values(ide_drive_t *drive, byte *buf){	(void) smart_enable(drive);	return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_VALUES, 1, buf);}static int get_smart_thresholds(ide_drive_t *drive, byte *buf){	(void) smart_enable(drive);	return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_THRESHOLDS, 1, 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) + 2;		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) + 2;		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 */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);	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 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,	"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,	2,	&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,	2,	&read_ahead[major],		NULL);	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	INT_MAX,			1,	1024,	&max_readahead[major][minor],	NULL);	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	2,	&max_sectors[major][minor],	NULL);	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);}/* *	IDE subdriver functions, registered with ide.c */static ide_driver_t idedisk_driver = {	"ide-disk",		/* name */	IDEDISK_VERSION,	/* version */	ide_disk,		/* media */	0,			/* busy */	1,			/* supports_dma */	0,			/* supports_dsc_overlap */	NULL,			/* cleanup */	do_rw_disk,		/* do_request */	NULL,			/* end_request */	NULL,			/* ioctl */	idedisk_open,		/* open */	idedisk_release,	/* release */	idedisk_media_change,	/* media_change */	idedisk_revalidate,	/* revalidate */	idedisk_pre_reset,	/* pre_reset */	idedisk_capacity,	/* capacity */	idedisk_special,	/* special */	idedisk_proc		/* proc */};int idedisk_init (void);static ide_module_t idedisk_module = {	IDE_DRIVER_MODULE,	idedisk_init,	&idedisk_driver,	NULL};static int idedisk_cleanup (ide_drive_t *drive){	return ide_unregister_subdriver(drive);}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	}	drive->no_io_32bit = id->dword_io ? 1 : 0;}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;		}		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);			continue;		}		failed--;	}	ide_register_module(&idedisk_module);	MOD_DEC_USE_COUNT;	return 0;}#ifdef MODULEint init_module (void){	return idedisk_init();}void cleanup_module (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 */		if (drive->proc)			ide_remove_proc_entries(drive->proc, idedisk_proc);	}	ide_unregister_module(&idedisk_module);}#endif /* MODULE */

⌨️ 快捷键说明

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