This source file includes following definitions.
- scsi_bios_ptable
- scsicam_bios_param
- scsi_partsize
- setsize
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/fs.h>
17 #include <linux/genhd.h>
18 #include <linux/kernel.h>
19 #include <linux/blkdev.h>
20 #include <asm/unaligned.h>
21
22 #include <scsi/scsicam.h>
23
24
25 static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
26 unsigned int *secs);
27
28
29
30
31
32
33
34
35
36 unsigned char *scsi_bios_ptable(struct block_device *dev)
37 {
38 unsigned char *res = kmalloc(66, GFP_KERNEL);
39 if (res) {
40 struct block_device *bdev = dev->bd_contains;
41 Sector sect;
42 void *data = read_dev_sector(bdev, 0, §);
43 if (data) {
44 memcpy(res, data + 0x1be, 66);
45 put_dev_sector(sect);
46 } else {
47 kfree(res);
48 res = NULL;
49 }
50 }
51 return res;
52 }
53 EXPORT_SYMBOL(scsi_bios_ptable);
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
69 {
70 unsigned char *p;
71 u64 capacity64 = capacity;
72 int ret;
73
74 p = scsi_bios_ptable(bdev);
75 if (!p)
76 return -1;
77
78
79 ret = scsi_partsize(p, (unsigned long)capacity, (unsigned int *)ip + 2,
80 (unsigned int *)ip + 0, (unsigned int *)ip + 1);
81 kfree(p);
82
83 if (ret == -1 && capacity64 < (1ULL << 32)) {
84
85
86
87 ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
88 (unsigned int *)ip + 0, (unsigned int *)ip + 1);
89 }
90
91
92
93 if (ret || ip[0] > 255 || ip[1] > 63) {
94 if ((capacity >> 11) > 65534) {
95 ip[0] = 255;
96 ip[1] = 63;
97 } else {
98 ip[0] = 64;
99 ip[1] = 32;
100 }
101
102 if (capacity > 65535*63*255)
103 ip[2] = 65535;
104 else
105 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
106 }
107
108 return 0;
109 }
110 EXPORT_SYMBOL(scsicam_bios_param);
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 int scsi_partsize(unsigned char *buf, unsigned long capacity,
127 unsigned int *cyls, unsigned int *hds, unsigned int *secs)
128 {
129 struct partition *p = (struct partition *)buf, *largest = NULL;
130 int i, largest_cyl;
131 int cyl, ext_cyl, end_head, end_cyl, end_sector;
132 unsigned int logical_end, physical_end, ext_physical_end;
133
134
135 if (*(unsigned short *) (buf + 64) == 0xAA55) {
136 for (largest_cyl = -1, i = 0; i < 4; ++i, ++p) {
137 if (!p->sys_ind)
138 continue;
139 #ifdef DEBUG
140 printk("scsicam_bios_param : partition %d has system \n",
141 i);
142 #endif
143 cyl = p->cyl + ((p->sector & 0xc0) << 2);
144 if (cyl > largest_cyl) {
145 largest_cyl = cyl;
146 largest = p;
147 }
148 }
149 }
150 if (largest) {
151 end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
152 end_head = largest->end_head;
153 end_sector = largest->end_sector & 0x3f;
154
155 if (end_head + 1 == 0 || end_sector == 0)
156 return -1;
157
158 #ifdef DEBUG
159 printk("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
160 end_head, end_cyl, end_sector);
161 #endif
162
163 physical_end = end_cyl * (end_head + 1) * end_sector +
164 end_head * end_sector + end_sector;
165
166
167 logical_end = get_unaligned_le32(&largest->start_sect)
168 + get_unaligned_le32(&largest->nr_sects);
169
170
171 ext_cyl = (logical_end - (end_head * end_sector + end_sector))
172 / (end_head + 1) / end_sector;
173 ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
174 end_head * end_sector + end_sector;
175
176 #ifdef DEBUG
177 printk("scsicam_bios_param : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n"
178 ,logical_end, physical_end, ext_physical_end, ext_cyl);
179 #endif
180
181 if ((logical_end == physical_end) ||
182 (end_cyl == 1023 && ext_physical_end == logical_end)) {
183 *secs = end_sector;
184 *hds = end_head + 1;
185 *cyls = capacity / ((end_head + 1) * end_sector);
186 return 0;
187 }
188 #ifdef DEBUG
189 printk("scsicam_bios_param : logical (%u) != physical (%u)\n",
190 logical_end, physical_end);
191 #endif
192 }
193 return -1;
194 }
195 EXPORT_SYMBOL(scsi_partsize);
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
232 unsigned int *secs)
233 {
234 unsigned int rv = 0;
235 unsigned long heads, sectors, cylinders, temp;
236
237 cylinders = 1024L;
238 sectors = 62L;
239
240 temp = cylinders * sectors;
241 heads = capacity / temp;
242 if (capacity % temp) {
243 heads++;
244 temp = cylinders * heads;
245 sectors = capacity / temp;
246
247 if (capacity % temp) {
248 sectors++;
249 temp = heads * sectors;
250 cylinders = capacity / temp;
251 }
252 }
253 if (cylinders == 0)
254 rv = (unsigned) -1;
255
256 *cyls = (unsigned int) cylinders;
257 *secs = (unsigned int) sectors;
258 *hds = (unsigned int) heads;
259 return (rv);
260 }