forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/scsi/scsicam.c
....@@ -17,13 +17,10 @@
1717 #include <linux/genhd.h>
1818 #include <linux/kernel.h>
1919 #include <linux/blkdev.h>
20
+#include <linux/msdos_partition.h>
2021 #include <asm/unaligned.h>
2122
2223 #include <scsi/scsicam.h>
23
-
24
-
25
-static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
26
- unsigned int *secs);
2724
2825 /**
2926 * scsi_bios_ptable - Read PC partition table out of first sector of device.
....@@ -35,105 +32,48 @@
3532 */
3633 unsigned char *scsi_bios_ptable(struct block_device *dev)
3734 {
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, &sect);
43
- if (data) {
44
- memcpy(res, data + 0x1be, 66);
45
- put_dev_sector(sect);
46
- } else {
47
- kfree(res);
48
- res = NULL;
49
- }
50
- }
35
+ struct address_space *mapping = dev->bd_contains->bd_inode->i_mapping;
36
+ unsigned char *res = NULL;
37
+ struct page *page;
38
+
39
+ page = read_mapping_page(mapping, 0, NULL);
40
+ if (IS_ERR(page))
41
+ return NULL;
42
+
43
+ if (!PageError(page))
44
+ res = kmemdup(page_address(page) + 0x1be, 66, GFP_KERNEL);
45
+ put_page(page);
5146 return res;
5247 }
5348 EXPORT_SYMBOL(scsi_bios_ptable);
5449
5550 /**
56
- * scsicam_bios_param - Determine geometry of a disk in cylinders/heads/sectors.
57
- * @bdev: which device
58
- * @capacity: size of the disk in sectors
59
- * @ip: return value: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders
60
- *
61
- * Description : determine the BIOS mapping/geometry used for a drive in a
62
- * SCSI-CAM system, storing the results in ip as required
63
- * by the HDIO_GETGEO ioctl().
64
- *
65
- * Returns : -1 on failure, 0 on success.
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; /* Suppress gcc warning */
72
- int ret;
73
-
74
- p = scsi_bios_ptable(bdev);
75
- if (!p)
76
- return -1;
77
-
78
- /* try to infer mapping from partition table */
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
- /* pick some standard mapping with at most 1024 cylinders,
85
- and at most 62 sectors per track - this works up to
86
- 7905 MB */
87
- ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
88
- (unsigned int *)ip + 0, (unsigned int *)ip + 1);
89
- }
90
-
91
- /* if something went wrong, then apparently we have to return
92
- a geometry with more than 1024 cylinders */
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
-/**
11351 * scsi_partsize - Parse cylinders/heads/sectors from PC partition table
114
- * @buf: partition table, see scsi_bios_ptable()
52
+ * @bdev: block device to parse
11553 * @capacity: size of the disk in sectors
116
- * @cyls: put cylinders here
117
- * @hds: put heads here
118
- * @secs: put sectors here
54
+ * @geom: output in form of [hds, cylinders, sectors]
11955 *
12056 * Determine the BIOS mapping/geometry used to create the partition
121
- * table, storing the results in @cyls, @hds, and @secs
57
+ * table, storing the results in @geom.
12258 *
123
- * Returns: -1 on failure, 0 on success.
59
+ * Returns: %false on failure, %true on success.
12460 */
125
-
126
-int scsi_partsize(unsigned char *buf, unsigned long capacity,
127
- unsigned int *cyls, unsigned int *hds, unsigned int *secs)
61
+bool scsi_partsize(struct block_device *bdev, sector_t capacity, int geom[3])
12862 {
129
- struct partition *p = (struct partition *)buf, *largest = NULL;
130
- int i, largest_cyl;
13163 int cyl, ext_cyl, end_head, end_cyl, end_sector;
13264 unsigned int logical_end, physical_end, ext_physical_end;
65
+ struct msdos_partition *p, *largest = NULL;
66
+ void *buf;
67
+ int ret = false;
13368
69
+ buf = scsi_bios_ptable(bdev);
70
+ if (!buf)
71
+ return false;
13472
13573 if (*(unsigned short *) (buf + 64) == 0xAA55) {
136
- for (largest_cyl = -1, i = 0; i < 4; ++i, ++p) {
74
+ int largest_cyl = -1, i;
75
+
76
+ for (i = 0, p = buf; i < 4; i++, p++) {
13777 if (!p->sys_ind)
13878 continue;
13979 #ifdef DEBUG
....@@ -153,7 +93,7 @@
15393 end_sector = largest->end_sector & 0x3f;
15494
15595 if (end_head + 1 == 0 || end_sector == 0)
156
- return -1;
96
+ goto out_free_buf;
15797
15898 #ifdef DEBUG
15999 printk("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
....@@ -178,19 +118,24 @@
178118 ,logical_end, physical_end, ext_physical_end, ext_cyl);
179119 #endif
180120
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;
121
+ if (logical_end == physical_end ||
122
+ (end_cyl == 1023 && ext_physical_end == logical_end)) {
123
+ geom[0] = end_head + 1;
124
+ geom[1] = end_sector;
125
+ geom[2] = (unsigned long)capacity /
126
+ ((end_head + 1) * end_sector);
127
+ ret = true;
128
+ goto out_free_buf;
187129 }
188130 #ifdef DEBUG
189131 printk("scsicam_bios_param : logical (%u) != physical (%u)\n",
190132 logical_end, physical_end);
191133 #endif
192134 }
193
- return -1;
135
+
136
+out_free_buf:
137
+ kfree(buf);
138
+ return ret;
194139 }
195140 EXPORT_SYMBOL(scsi_partsize);
196141
....@@ -258,3 +203,56 @@
258203 *hds = (unsigned int) heads;
259204 return (rv);
260205 }
206
+
207
+/**
208
+ * scsicam_bios_param - Determine geometry of a disk in cylinders/heads/sectors.
209
+ * @bdev: which device
210
+ * @capacity: size of the disk in sectors
211
+ * @ip: return value: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders
212
+ *
213
+ * Description : determine the BIOS mapping/geometry used for a drive in a
214
+ * SCSI-CAM system, storing the results in ip as required
215
+ * by the HDIO_GETGEO ioctl().
216
+ *
217
+ * Returns : -1 on failure, 0 on success.
218
+ */
219
+int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
220
+{
221
+ u64 capacity64 = capacity; /* Suppress gcc warning */
222
+ int ret = 0;
223
+
224
+ /* try to infer mapping from partition table */
225
+ if (scsi_partsize(bdev, capacity, ip))
226
+ return 0;
227
+
228
+ if (capacity64 < (1ULL << 32)) {
229
+ /*
230
+ * Pick some standard mapping with at most 1024 cylinders, and
231
+ * at most 62 sectors per track - this works up to 7905 MB.
232
+ */
233
+ ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
234
+ (unsigned int *)ip + 0, (unsigned int *)ip + 1);
235
+ }
236
+
237
+ /*
238
+ * If something went wrong, then apparently we have to return a geometry
239
+ * with more than 1024 cylinders.
240
+ */
241
+ if (ret || ip[0] > 255 || ip[1] > 63) {
242
+ if ((capacity >> 11) > 65534) {
243
+ ip[0] = 255;
244
+ ip[1] = 63;
245
+ } else {
246
+ ip[0] = 64;
247
+ ip[1] = 32;
248
+ }
249
+
250
+ if (capacity > 65535*63*255)
251
+ ip[2] = 65535;
252
+ else
253
+ ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
254
+ }
255
+
256
+ return 0;
257
+}
258
+EXPORT_SYMBOL(scsicam_bios_param);