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

📄 ide-disk.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
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 */}/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */static unsigned long 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 != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {		if (id->lba_capacity >= capacity) {			drive->cyl = id->lba_capacity / (drive->head * drive->sect);			capacity = id->lba_capacity;			drive->select.b.lba = 1;		}	}	return (capacity - drive->sect0);}static void 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);	}}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->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){	unsigned long flags;	if (ide_spin_wait_hwgroup(drive, &flags))		return -EBUSY;	drive->nowerr = arg;	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);	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_SHORT,	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 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_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){	struct hd_driveid *id = drive->id;	unsigned long capacity, check;		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;		}	}	/* 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) {		/*		 * Extract the physical drive geometry for our use.		 * Note that we purposely do *not* update the bios info.		 * This way, programs that use it (like fdisk) will		 * still have the same logical view as the BIOS does,		 * which keeps the partition table from being screwed.		 *		 * An exception to this is the cylinder count,		 * which we reexamine later on to correct for 1024 limitations.		 */		drive->cyl  = id->cur_cyls;		drive->head = id->cur_heads;		drive->sect = id->cur_sectors;		/* check for word-swapped "capacity" field in id information */		capacity = drive->cyl * drive->head * drive->sect;		check = (id->cur_capacity0 << 16) | id->cur_capacity1;		if (check == capacity) {	/* was it swapped? */			/* yes, bring it into little-endian order: */			id->cur_capacity0 = (capacity >>  0) & 0xffff;			id->cur_capacity1 = (capacity >> 16) & 0xffff;		}	}	/* Use physical geometry if what we have still makes no sense */	if ((!drive->head || drive->head > 16) &&	    id->heads && id->heads <= 16) {		if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) {			id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors)));		}		drive->cyl  = id->cur_cyls    = id->cyls;		drive->head = id->cur_heads   = id->heads;		drive->sect = id->cur_sectors = id->sectors;	}	/* calculate drive capacity, and select LBA if possible */	capacity = idedisk_capacity (drive);	/*	 * if possible, give fdisk access to more of the drive,	 * by correcting bios_cyls:	 */	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;#ifdef DEBUG		printk("Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",			drive->id->cur_cyls,			drive->id->cur_heads,			drive->id->cur_sectors,			drive->bios_cyl,			drive->bios_head,			drive->bios_sect);#endif		drive->id->cur_cyls    = drive->bios_cyl;		drive->id->cur_heads   = drive->bios_head;		drive->id->cur_sectors = drive->bios_sect;	}#if 0	/* done instead for entire identify block in arch/ide.h stuff */	/* fix byte-ordering of buffer size field */	id->buf_size = le16_to_cpu(id->buf_size);#endif	printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",			drive->name, id->model,			capacity/2048L, id->buf_size/2,			drive->bios_cyl, drive->bios_head, drive->bios_sect);	if (drive->using_dma) {		if ((id->field_valid & 4) &&		    (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {			printk(", UDMA");	/* UDMA BIOS-enabled! */		} else if (id->field_valid & 4) {			printk(", (U)DMA");	/* Can be BIOS-enabled! */		} else {			printk(", DMA");		}	}	printk("\n");	if (drive->select.b.lba) {		if (*(int *)&id->cur_capacity0 < id->lba_capacity) {#ifdef DEBUG			printk("     CurSects=%d, LBASects=%d, ",				*(int *)&id->cur_capacity0, id->lba_capacity);#endif			*(int *)&id->cur_capacity0 = id->lba_capacity;#ifdef DEBUG			printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0);#endif		}	}	drive->mult_count = 0;	if (id->max_multsect) {#if 1	/* 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;#else		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;#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++;		}	ide_unregister_module(&idedisk_module);}#endif /* MODULE */

⌨️ 快捷键说明

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