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

📄 ide-geometry.c

📁 ep9315平台下硬盘驱动的源码
💻 C
字号:
/* * linux/drivers/ide/ide-geometry.c */#include <linux/config.h>#include <linux/ide.h>#include <linux/mc146818rtc.h>#include <asm/io.h>/* * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc * controller that is BIOS compatible with ST-506, and thus showing up in our * BIOS table, but not register compatible, and therefore not present in CMOS. * * Furthermore, we will assume that our ST-506 drives <if any> are the primary * drives in the system -- the ones reflected as drive 1 or 2.  The first * drive is stored in the high nibble of CMOS byte 0x12, the second in the low * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value * means we have an AT controller hard disk for that drive. * * Of course, there is no guarantee that either drive is actually on the * "primary" IDE interface, but we don't bother trying to sort that out here. * If a drive is not actually on the primary interface, then these parameters * will be ignored.  This results in the user having to supply the logical * drive geometry as a boot parameter for each drive not on the primary i/f. * * The only "perfect" way to handle this would be to modify the setup.[cS] code * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info * for us during initialization.  I have the necessary docs -- any takers?  -ml * * I did this, but it doesn't work - there is no reasonable way to find the * correspondence between the BIOS numbering of the disks and the Linux * numbering. -aeb * * The code below is bad. One of the problems is that drives 1 and 2 * may be SCSI disks (even when IDE disks are present), so that * the geometry we read here from BIOS is attributed to the wrong disks. * Consequently, also the former "drive->present = 1" below was a mistake. * * Eventually the entire routine below should be removed. * * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS * chip. */void probe_cmos_for_drives (ide_hwif_t *hwif){#ifdef __i386__	extern struct drive_info_struct drive_info;	u8 cmos_disks, *BIOS = (u8 *) &drive_info;	int unit;	unsigned long flags;	if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)		return;	spin_lock_irqsave(&rtc_lock, flags);	cmos_disks = CMOS_READ(0x12);	spin_unlock_irqrestore(&rtc_lock, flags);	/* Extract drive geometry from CMOS+BIOS if not already setup */	for (unit = 0; unit < MAX_DRIVES; ++unit) {		ide_drive_t *drive = &hwif->drives[unit];		if ((cmos_disks & (0xf0 >> (unit*4)))		   && !drive->present && !drive->nobios) {			u16 cyl = *(u16 *)BIOS;			unsigned char head = *(BIOS+2);			unsigned char sect = *(BIOS+14);			if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {				drive->cyl   = drive->bios_cyl  = cyl;				drive->head  = drive->bios_head = head;				drive->sect  = drive->bios_sect = sect;				drive->ctl   = *(BIOS+8);			} else {				printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n",				       unit+'a', cyl, head, sect);			}		}		BIOS += 16;	}#endif}extern ide_drive_t * get_info_ptr(kdev_t);extern unsigned long current_capacity (ide_drive_t *);/* * If heads is nonzero: find a translation with this many heads and S=63. * Otherwise: find out how OnTrack Disk Manager would translate the disk. */static void ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) {	static const u8 dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};	const u8 *headp = dm_head_vals;	unsigned long total;	/*	 * The specs say: take geometry as obtained from Identify,	 * compute total capacity C*H*S from that, and truncate to	 * 1024*255*63. Now take S=63, H the first in the sequence	 * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.	 * [Please tell aeb@cwi.nl in case this computes a	 * geometry different from what OnTrack uses.]	 */	total = DRIVER(drive)->capacity(drive);	*s = 63;	if (heads) {		*h = heads;		*c = total / (63 * heads);		return;	}	while (63 * headp[0] * 1024 < total && headp[1] != 0)		 headp++;	*h = headp[0];	*c = total / (63 * headp[0]);}/* * This routine is called from the partition-table code in pt/msdos.c. * It has two tasks: * (i) to handle Ontrack DiskManager by offsetting everything by 63 sectors, *  or to handle EZdrive by remapping sector 0 to sector 1. * (ii) to invent a translated geometry. * Part (i) is suppressed if the user specifies the "noremap" option * on the command line. * Part (ii) is suppressed if the user specifies an explicit geometry. * * The ptheads parameter is either 0 or tells about the number of * heads shown by the end of the first nonempty partition. * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it. * * The xparm parameter has the following meaning: *	 0 = convert to CHS with fewer than 1024 cyls *	     using the same method as Ontrack DiskManager. *	 1 = same as "0", plus offset everything by 63 sectors. *	-1 = similar to "0", plus redirect sector 0 to sector 1. *	 2 = convert to a CHS geometry with "ptheads" heads. * * Returns 0 if the translation was not possible, if the device was not  * an IDE disk drive, or if a geometry was "forced" on the commandline. * Returns 1 if the geometry translation was successful. */int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg){	ide_drive_t *drive;	const char *msg1 = "";	int heads = 0;	int c, h, s;	int transl = 1;		/* try translation */	int ret = 0;	drive = get_info_ptr(i_rdev);	if (!drive)		return 0;	/* remap? */	if (drive->remap_0_to_1 != 2) {		if (xparm == 1) {		/* DM */			drive->sect0 = 63;			msg1 = " [remap +63]";			ret = 1;		} else if (xparm == -1) {	/* EZ-Drive */			if (drive->remap_0_to_1 == 0) {				drive->remap_0_to_1 = 1;				msg1 = " [remap 0->1]";				ret = 1;			}		}	}	/* There used to be code here that assigned drive->id->CHS	   to drive->CHS and that to drive->bios_CHS. However,	   some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.	   In such cases that code was wrong.  Moreover,	   there seems to be no reason to do any of these things. */	/* translate? */	if (drive->forced_geom)		transl = 0;	/* does ptheads look reasonable? */	if (ptheads == 32 || ptheads == 64 || ptheads == 128 ||	    ptheads == 240 || ptheads == 255)		heads = ptheads;	if (xparm == 2) {		if (!heads ||		   (drive->bios_head >= heads && drive->bios_sect == 63))			transl = 0;	}	if (xparm == -1) {		if (drive->bios_head > 16)			transl = 0;     /* we already have a translation */	}	if (transl) {		ontrack(drive, heads, &c, &h, &s);		drive->bios_cyl = c;		drive->bios_head = h;		drive->bios_sect = s;		ret = 1;	}	drive->part[0].nr_sects = current_capacity(drive);	if (ret)		printk("%s%s [%d/%d/%d]", msg, msg1,		       drive->bios_cyl, drive->bios_head, drive->bios_sect);	return ret;}

⌨️ 快捷键说明

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