OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [ide-geometry.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/drivers/ide/ide-geometry.c
3
 */
4
#include <linux/config.h>
5
#include <linux/ide.h>
6
#include <linux/mc146818rtc.h>
7
#include <asm/io.h>
8
 
9
/*
10
 * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
11
 * controller that is BIOS compatible with ST-506, and thus showing up in our
12
 * BIOS table, but not register compatible, and therefore not present in CMOS.
13
 *
14
 * Furthermore, we will assume that our ST-506 drives <if any> are the primary
15
 * drives in the system -- the ones reflected as drive 1 or 2.  The first
16
 * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
17
 * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
18
 * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value
19
 * means we have an AT controller hard disk for that drive.
20
 *
21
 * Of course, there is no guarantee that either drive is actually on the
22
 * "primary" IDE interface, but we don't bother trying to sort that out here.
23
 * If a drive is not actually on the primary interface, then these parameters
24
 * will be ignored.  This results in the user having to supply the logical
25
 * drive geometry as a boot parameter for each drive not on the primary i/f.
26
 *
27
 * The only "perfect" way to handle this would be to modify the setup.[cS] code
28
 * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
29
 * for us during initialization.  I have the necessary docs -- any takers?  -ml
30
 *
31
 * I did this, but it doesn't work - there is no reasonable way to find the
32
 * correspondence between the BIOS numbering of the disks and the Linux
33
 * numbering. -aeb
34
 *
35
 * The code below is bad. One of the problems is that drives 1 and 2
36
 * may be SCSI disks (even when IDE disks are present), so that
37
 * the geometry we read here from BIOS is attributed to the wrong disks.
38
 * Consequently, also the former "drive->present = 1" below was a mistake.
39
 *
40
 * Eventually the entire routine below should be removed.
41
 *
42
 * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS
43
 * chip.
44
 */
45
 
46
void probe_cmos_for_drives (ide_hwif_t *hwif)
47
{
48
#ifdef __i386__
49
        extern struct drive_info_struct drive_info;
50
        u8 cmos_disks, *BIOS = (u8 *) &drive_info;
51
        int unit;
52
        unsigned long flags;
53
 
54
        if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
55
                return;
56
 
57
        spin_lock_irqsave(&rtc_lock, flags);
58
        cmos_disks = CMOS_READ(0x12);
59
        spin_unlock_irqrestore(&rtc_lock, flags);
60
        /* Extract drive geometry from CMOS+BIOS if not already setup */
61
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
62
                ide_drive_t *drive = &hwif->drives[unit];
63
 
64
                if ((cmos_disks & (0xf0 >> (unit*4)))
65
                   && !drive->present && !drive->nobios) {
66
                        u16 cyl = *(u16 *)BIOS;
67
                        unsigned char head = *(BIOS+2);
68
                        unsigned char sect = *(BIOS+14);
69
                        if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
70
                                drive->cyl   = drive->bios_cyl  = cyl;
71
                                drive->head  = drive->bios_head = head;
72
                                drive->sect  = drive->bios_sect = sect;
73
                                drive->ctl   = *(BIOS+8);
74
                        } else {
75
                                printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n",
76
                                       unit+'a', cyl, head, sect);
77
                        }
78
                }
79
 
80
                BIOS += 16;
81
        }
82
#endif
83
}
84
 
85
 
86
extern unsigned long current_capacity (ide_drive_t *);
87
 
88
/*
89
 * If heads is nonzero: find a translation with this many heads and S=63.
90
 * Otherwise: find out how OnTrack Disk Manager would translate the disk.
91
 */
92
 
93
static void ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s)
94
{
95
        static const u8 dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
96
        const u8 *headp = dm_head_vals;
97
        unsigned long total;
98
 
99
        /*
100
         * The specs say: take geometry as obtained from Identify,
101
         * compute total capacity C*H*S from that, and truncate to
102
         * 1024*255*63. Now take S=63, H the first in the sequence
103
         * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.
104
         * [Please tell aeb@cwi.nl in case this computes a
105
         * geometry different from what OnTrack uses.]
106
         */
107
        total = DRIVER(drive)->capacity(drive);
108
 
109
        *s = 63;
110
 
111
        if (heads) {
112
                *h = heads;
113
                *c = total / (63 * heads);
114
                return;
115
        }
116
 
117
        while (63 * headp[0] * 1024 < total && headp[1] != 0)
118
                 headp++;
119
        *h = headp[0];
120
        *c = total / (63 * headp[0]);
121
}
122
 
123
/*
124
 * This routine is called from the partition-table code in pt/msdos.c.
125
 * It has two tasks:
126
 * (i) to handle Ontrack DiskManager by offsetting everything by 63 sectors,
127
 *  or to handle EZdrive by remapping sector 0 to sector 1.
128
 * (ii) to invent a translated geometry.
129
 * Part (i) is suppressed if the user specifies the "noremap" option
130
 * on the command line.
131
 * Part (ii) is suppressed if the user specifies an explicit geometry.
132
 *
133
 * The ptheads parameter is either 0 or tells about the number of
134
 * heads shown by the end of the first nonempty partition.
135
 * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it.
136
 *
137
 * The xparm parameter has the following meaning:
138
 *       0 = convert to CHS with fewer than 1024 cyls
139
 *           using the same method as Ontrack DiskManager.
140
 *       1 = same as "0", plus offset everything by 63 sectors.
141
 *      -1 = similar to "0", plus redirect sector 0 to sector 1.
142
 *       2 = convert to a CHS geometry with "ptheads" heads.
143
 *
144
 * Returns 0 if the translation was not possible, if the device was not
145
 * an IDE disk drive, or if a geometry was "forced" on the commandline.
146
 * Returns 1 if the geometry translation was successful.
147
 */
148
 
149
int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg)
150
{
151
        ide_drive_t *drive;
152
        const char *msg1 = "";
153
        int heads = 0;
154
        int c, h, s;
155
        int transl = 1;         /* try translation */
156
        int ret = 0;
157
 
158
        drive = ide_info_ptr(i_rdev, 0);
159
        if (!drive)
160
                return 0;
161
 
162
        /* remap? */
163
        if (drive->remap_0_to_1 != 2) {
164
                if (xparm == 1) {               /* DM */
165
                        drive->sect0 = 63;
166
                        msg1 = " [remap +63]";
167
                        ret = 1;
168
                } else if (xparm == -1) {       /* EZ-Drive */
169
                        if (drive->remap_0_to_1 == 0) {
170
                                drive->remap_0_to_1 = 1;
171
                                msg1 = " [remap 0->1]";
172
                                ret = 1;
173
                        }
174
                }
175
        }
176
 
177
        /* There used to be code here that assigned drive->id->CHS
178
           to drive->CHS and that to drive->bios_CHS. However,
179
           some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.
180
           In such cases that code was wrong.  Moreover,
181
           there seems to be no reason to do any of these things. */
182
 
183
        /* translate? */
184
        if (drive->forced_geom)
185
                transl = 0;
186
 
187
        /* does ptheads look reasonable? */
188
        if (ptheads == 32 || ptheads == 64 || ptheads == 128 ||
189
            ptheads == 240 || ptheads == 255)
190
                heads = ptheads;
191
 
192
        if (xparm == 2) {
193
                if (!heads ||
194
                   (drive->bios_head >= heads && drive->bios_sect == 63))
195
                        transl = 0;
196
        }
197
        if (xparm == -1) {
198
                if (drive->bios_head > 16)
199
                        transl = 0;     /* we already have a translation */
200
        }
201
 
202
        if (transl) {
203
                ontrack(drive, heads, &c, &h, &s);
204
                drive->bios_cyl = c;
205
                drive->bios_head = h;
206
                drive->bios_sect = s;
207
                ret = 1;
208
        }
209
 
210
        drive->part[0].nr_sects = current_capacity(drive);
211
 
212
        if (ret)
213
                printk("%s%s [%d/%d/%d]", msg, msg1,
214
                       drive->bios_cyl, drive->bios_head, drive->bios_sect);
215
        return ret;
216
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.