blob: df5fe5756871ca31b135a736dfc64f9d1097bec6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Bartlomiej Zolnierkiewicz59bca8c2008-02-01 23:09:33 +01002 * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
3 * Copyright (C) 1998-2002 Linux ATA Development
4 * Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2003 Red Hat <alan@redhat.com>
6 * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
9/*
10 * Mostly written by Mark Lord <mlord@pobox.com>
11 * and Gadi Oxman <gadio@netvision.net.il>
12 * and Andre Hedrick <andre@linux-ide.org>
13 *
14 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 */
16
17#define IDEDISK_VERSION "1.18"
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/mm.h>
25#include <linux/interrupt.h>
26#include <linux/major.h>
27#include <linux/errno.h>
28#include <linux/genhd.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080031#include <linux/mutex.h>
Richard Purdie2bfb6462006-03-31 02:31:16 -080032#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#define _IDE_DISK
35
36#include <linux/ide.h>
37
38#include <asm/byteorder.h>
39#include <asm/irq.h>
40#include <asm/uaccess.h>
41#include <asm/io.h>
42#include <asm/div64.h>
43
44struct ide_disk_obj {
45 ide_drive_t *drive;
46 ide_driver_t *driver;
47 struct gendisk *disk;
48 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010049 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070050};
51
Arjan van de Vencf8b8972006-03-23 03:00:45 -080052static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
55
56#define ide_disk_g(disk) \
57 container_of((disk)->private_data, struct ide_disk_obj, driver)
58
59static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
60{
61 struct ide_disk_obj *idkp = NULL;
62
Arjan van de Vencf8b8972006-03-23 03:00:45 -080063 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 idkp = ide_disk_g(disk);
65 if (idkp)
66 kref_get(&idkp->kref);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080067 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 return idkp;
69}
70
71static void ide_disk_release(struct kref *);
72
73static void ide_disk_put(struct ide_disk_obj *idkp)
74{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080075 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 kref_put(&idkp->kref, ide_disk_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080077 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078}
79
80/*
81 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
82 * value for this drive (from its reported identification information).
83 *
84 * Returns: 1 if lba_capacity looks sensible
85 * 0 otherwise
86 *
87 * It is called only once for each drive.
88 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +020089static int lba_capacity_is_ok(struct hd_driveid *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
91 unsigned long lba_sects, chs_sects, head, tail;
92
Alan Cox6efd9362005-06-27 15:24:22 -070093 /* No non-LBA info .. so valid! */
94 if (id->cyls == 0)
95 return 1;
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 /*
98 * The ATA spec tells large drives to return
99 * C/H/S = 16383/16/63 independent of their size.
100 * Some drives can be jumpered to use 15 heads instead of 16.
101 * Some drives can be jumpered to use 4092 cyls instead of 16383.
102 */
103 if ((id->cyls == 16383
104 || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
105 id->sectors == 63 &&
106 (id->heads == 15 || id->heads == 16) &&
107 (id->lba_capacity >= 16383*63*id->heads))
108 return 1;
109
110 lba_sects = id->lba_capacity;
111 chs_sects = id->cyls * id->heads * id->sectors;
112
113 /* perform a rough sanity check on lba_sects: within 10% is OK */
114 if ((lba_sects - chs_sects) < chs_sects/10)
115 return 1;
116
117 /* some drives have the word order reversed */
118 head = ((lba_sects >> 16) & 0xffff);
119 tail = (lba_sects & 0xffff);
120 lba_sects = (head | (tail << 16));
121 if ((lba_sects - chs_sects) < chs_sects/10) {
122 id->lba_capacity = lba_sects;
123 return 1; /* lba_capacity is (now) good */
124 }
125
126 return 0; /* lba_capacity value may be bad */
127}
128
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100129static const u8 ide_rw_cmds[] = {
130 WIN_MULTREAD,
131 WIN_MULTWRITE,
132 WIN_MULTREAD_EXT,
133 WIN_MULTWRITE_EXT,
134 WIN_READ,
135 WIN_WRITE,
136 WIN_READ_EXT,
137 WIN_WRITE_EXT,
138 WIN_READDMA,
139 WIN_WRITEDMA,
140 WIN_READDMA_EXT,
141 WIN_WRITEDMA_EXT,
142};
143
144static const u8 ide_data_phases[] = {
145 TASKFILE_MULTI_IN,
146 TASKFILE_MULTI_OUT,
147 TASKFILE_IN,
148 TASKFILE_OUT,
149 TASKFILE_IN_DMA,
150 TASKFILE_OUT_DMA,
151};
152
153static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
154{
155 u8 index, lba48, write;
156
157 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
158 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
159
160 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200161 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100162 else
163 index = drive->mult_count ? 0 : 4;
164
165 task->tf.command = ide_rw_cmds[index + lba48 + write];
166
167 if (dma)
168 index = 8; /* fixup index */
169
170 task->data_phase = ide_data_phases[index / 2 + write];
171}
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173/*
174 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
175 * using LBA if supported, or CHS otherwise, to address sectors.
176 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200177static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
178 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179{
180 ide_hwif_t *hwif = HWIF(drive);
181 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100182 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100184 ide_task_t task;
185 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100186 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200188 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 if (block + rq->nr_sectors > 1ULL << 28)
190 dma = 0;
191 else
192 lba48 = 0;
193 }
194
195 if (!dma) {
196 ide_init_sg_cmd(drive, rq);
197 ide_map_sg(drive, rq);
198 }
199
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100200 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200201 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 if (drive->select.b.lba) {
204 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800205 pr_debug("%s: LBA=0x%012llx\n", drive->name,
206 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100208 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100209 tf->hob_lbal = (u8)(block >> 24);
210 if (sizeof(block) != 4) {
211 tf->hob_lbam = (u8)((u64)block >> 32);
212 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100214
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100215 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100216 tf->lbal = (u8) block;
217 tf->lbam = (u8)(block >> 8);
218 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100219
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100220 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100222 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100223 tf->lbal = block;
224 tf->lbam = block >>= 8;
225 tf->lbah = block >>= 8;
226 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200229 unsigned int sect, head, cyl, track;
230
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 track = (int)block / drive->sect;
232 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 head = track % drive->head;
234 cyl = track / drive->head;
235
236 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
237
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100238 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100239 tf->lbal = sect;
240 tf->lbam = cyl;
241 tf->lbah = cyl >> 8;
242 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
244
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100245 if (rq_data_dir(rq))
246 task.tf_flags |= IDE_TFLAG_WRITE;
247
248 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100249 if (!dma)
250 hwif->data_phase = task.data_phase;
251 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100252
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100253 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100254
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100255 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100257 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100258 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100259 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100261 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 }
263
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100264 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265}
266
267/*
268 * 268435455 == 137439 MB or 28bit limit
269 * 320173056 == 163929 MB or 48bit addressing
270 * 1073741822 == 549756 MB or 48bit addressing fake drive
271 */
272
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200273static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
274 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 ide_hwif_t *hwif = HWIF(drive);
277
278 BUG_ON(drive->blocked);
279
280 if (!blk_fs_request(rq)) {
281 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
282 ide_end_request(drive, 0, 0);
283 return ide_stopped;
284 }
285
Richard Purdie2bfb6462006-03-31 02:31:16 -0800286 ledtrig_ide_activity();
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
289 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800290 (unsigned long long)block, rq->nr_sectors,
291 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
293 if (hwif->rw_disk)
294 hwif->rw_disk(drive, rq);
295
296 return __ide_do_rw_disk(drive, rq, block);
297}
298
299/*
300 * Queries for true maximum capacity of the drive.
301 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
302 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100303static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
305 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100306 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100307 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 /* Create IDE/ATA command request structure */
310 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100311 if (lba48)
312 tf->command = WIN_READ_NATIVE_MAX_EXT;
313 else
314 tf->command = WIN_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100315 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100316 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100317 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100318 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100320 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
322 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100323 if ((tf->status & 0x01) == 0)
324 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 return addr;
327}
328
329/*
330 * Sets maximum virtual LBA address of the drive.
331 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
332 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100333static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
335 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100336 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100337 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
339 addr_req--;
340 /* Create IDE/ATA command request structure */
341 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100342 tf->lbal = (addr_req >> 0) & 0xff;
343 tf->lbam = (addr_req >>= 8) & 0xff;
344 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100345 if (lba48) {
346 tf->hob_lbal = (addr_req >>= 8) & 0xff;
347 tf->hob_lbam = (addr_req >>= 8) & 0xff;
348 tf->hob_lbah = (addr_req >>= 8) & 0xff;
349 tf->command = WIN_SET_MAX_EXT;
350 } else {
351 tf->device = (addr_req >>= 8) & 0x0f;
352 tf->command = WIN_SET_MAX;
353 }
354 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100355 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100356 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100357 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100359 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100361 if ((tf->status & 0x01) == 0)
362 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 return addr_set;
365}
366
367static unsigned long long sectors_to_MB(unsigned long long n)
368{
369 n <<= 9; /* make it bytes */
370 do_div(n, 1000000); /* make it MB */
371 return n;
372}
373
374/*
375 * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
376 * so on non-buggy drives we need test only one.
377 * However, we should also check whether these fields are valid.
378 */
379static inline int idedisk_supports_hpa(const struct hd_driveid *id)
380{
381 return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
382}
383
384/*
385 * The same here.
386 */
387static inline int idedisk_supports_lba48(const struct hd_driveid *id)
388{
389 return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)
390 && id->lba_capacity_2;
391}
392
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200393/*
394 * Some disks report total number of sectors instead of
395 * maximum sector address. We list them here.
396 */
397static const struct drive_list_entry hpa_list[] = {
398 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200399 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100400 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200401 { NULL, NULL }
402};
403
Arjan van de Ven858119e2006-01-14 13:20:43 -0800404static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
406 unsigned long long capacity, set_max;
407 int lba48 = idedisk_supports_lba48(drive->id);
408
409 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100410
411 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200413 if (ide_in_drive_list(drive->id, hpa_list)) {
414 /*
415 * Since we are inclusive wrt to firmware revisions do this
416 * extra check and apply the workaround only when needed.
417 */
418 if (set_max == capacity + 1)
419 set_max--;
420 }
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 if (set_max <= capacity)
423 return;
424
425 printk(KERN_INFO "%s: Host Protected Area detected.\n"
426 "\tcurrent capacity is %llu sectors (%llu MB)\n"
427 "\tnative capacity is %llu sectors (%llu MB)\n",
428 drive->name,
429 capacity, sectors_to_MB(capacity),
430 set_max, sectors_to_MB(set_max));
431
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100432 set_max = idedisk_set_max_address(drive, set_max, lba48);
433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 if (set_max) {
435 drive->capacity64 = set_max;
436 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
437 drive->name);
438 }
439}
440
441/*
442 * Compute drive->capacity, the full capacity of the drive
443 * Called with drive->id != NULL.
444 *
445 * To compute capacity, this uses either of
446 *
447 * 1. CHS value set by user (whatever user sets will be trusted)
448 * 2. LBA value from target drive (require new ATA feature)
449 * 3. LBA value from system BIOS (new one is OK, old one may break)
450 * 4. CHS value from system BIOS (traditional style)
451 *
452 * in above order (i.e., if value of higher priority is available,
453 * reset will be ignored).
454 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200455static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 struct hd_driveid *id = drive->id;
458 /*
459 * If this drive supports the Host Protected Area feature set,
460 * then we may need to change our opinion about the drive's capacity.
461 */
462 int hpa = idedisk_supports_hpa(id);
463
464 if (idedisk_supports_lba48(id)) {
465 /* drive speaks 48-bit LBA */
466 drive->select.b.lba = 1;
467 drive->capacity64 = id->lba_capacity_2;
468 if (hpa)
469 idedisk_check_hpa(drive);
470 } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
471 /* drive speaks 28-bit LBA */
472 drive->select.b.lba = 1;
473 drive->capacity64 = id->lba_capacity;
474 if (hpa)
475 idedisk_check_hpa(drive);
476 } else {
477 /* drive speaks boring old 28-bit CHS */
478 drive->capacity64 = drive->cyl * drive->head * drive->sect;
479 }
480}
481
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200482static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
484 return drive->capacity64 - drive->sect0;
485}
486
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200487#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488static int smart_enable(ide_drive_t *drive)
489{
490 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100491 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100494 tf->feature = SMART_ENABLE;
495 tf->lbam = SMART_LCYL_PASS;
496 tf->lbah = SMART_HCYL_PASS;
497 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100498 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100499 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
501
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200502static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503{
504 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100505 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100508 tf->feature = sub_cmd;
509 tf->nsect = 0x01;
510 tf->lbam = SMART_LCYL_PASS;
511 tf->lbah = SMART_HCYL_PASS;
512 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100513 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100514 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100516 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517}
518
519static int proc_idedisk_read_cache
520 (char *page, char **start, off_t off, int count, int *eof, void *data)
521{
522 ide_drive_t *drive = (ide_drive_t *) data;
523 char *out = page;
524 int len;
525
526 if (drive->id_read)
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200527 len = sprintf(out, "%i\n", drive->id->buf_size / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200529 len = sprintf(out, "(none)\n");
530
531 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
534static int proc_idedisk_read_capacity
535 (char *page, char **start, off_t off, int count, int *eof, void *data)
536{
537 ide_drive_t*drive = (ide_drive_t *)data;
538 int len;
539
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200540 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
541
542 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543}
544
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200545static int proc_idedisk_read_smart(char *page, char **start, off_t off,
546 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
548 ide_drive_t *drive = (ide_drive_t *)data;
549 int len = 0, i = 0;
550
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200551 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 unsigned short *val = (unsigned short *) page;
553 char *out = ((char *)val) + (SECTOR_WORDS * 4);
554 page = out;
555 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200556 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
557 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 val += 1;
559 } while (i < (SECTOR_WORDS * 2));
560 len = out - page;
561 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200562
563 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200566static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 (char *page, char **start, off_t off, int count, int *eof, void *data)
568{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200569 return proc_idedisk_read_smart(page, start, off, count, eof, data,
570 SMART_READ_VALUES);
571}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200573static int proc_idedisk_read_st
574 (char *page, char **start, off_t off, int count, int *eof, void *data)
575{
576 return proc_idedisk_read_smart(page, start, off, count, eof, data,
577 SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578}
579
580static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200581 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
582 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
583 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
584 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
585 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 { NULL, 0, NULL, NULL }
587};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200588#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Jens Axboe165125e2007-07-24 09:28:11 +0200590static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591{
592 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100593 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100595 /* FIXME: map struct ide_taskfile on rq->cmd[] */
596 BUG_ON(task == NULL);
597
598 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 if (ide_id_has_flush_cache_ext(drive->id) &&
600 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100601 task->tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 else
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100603 task->tf.command = WIN_FLUSH_CACHE;
604 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
605 IDE_TFLAG_DYN;
606 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100608 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200609 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100610 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613/*
614 * This is tightly woven into the driver->do_special can not touch.
615 * DON'T do it again until a total personality rewrite is committed.
616 */
617static int set_multcount(ide_drive_t *drive, int arg)
618{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200619 struct request *rq;
620 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200622 if (arg < 0 || arg > drive->id->max_multsect)
623 return -EINVAL;
624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 if (drive->special.b.set_multmode)
626 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100627
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200628 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
629 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 drive->mult_req = arg;
632 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200633 error = blk_execute_rq(drive->queue, NULL, rq, 0);
634 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 return (drive->mult_count == arg) ? 0 : -EIO;
637}
638
639static int set_nowerr(ide_drive_t *drive, int arg)
640{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200641 if (arg < 0 || arg > 1)
642 return -EINVAL;
643
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 if (ide_spin_wait_hwgroup(drive))
645 return -EBUSY;
646 drive->nowerr = arg;
647 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
648 spin_unlock_irq(&ide_lock);
649 return 0;
650}
651
Tejun Heo3e087b52006-01-06 09:57:31 +0100652static void update_ordered(ide_drive_t *drive)
653{
654 struct hd_driveid *id = drive->id;
655 unsigned ordered = QUEUE_ORDERED_NONE;
656 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100657
658 if (drive->wcache) {
659 unsigned long long capacity;
660 int barrier;
661 /*
662 * We must avoid issuing commands a drive does not
663 * understand or we may crash it. We check flush cache
664 * is supported. We also check we have the LBA48 flush
665 * cache if the drive capacity is too large. By this
666 * time we have trimmed the drive capacity if LBA48 is
667 * not available so we don't need to recheck that.
668 */
669 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200670 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100671 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
672 ide_id_has_flush_cache_ext(id));
673
674 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800675 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100676
677 if (barrier) {
678 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
679 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100680 }
681 } else
682 ordered = QUEUE_ORDERED_DRAIN;
683
684 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100685}
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687static int write_cache(ide_drive_t *drive, int arg)
688{
689 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100690 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200692 if (arg < 0 || arg > 1)
693 return -EINVAL;
694
Tejun Heo3e087b52006-01-06 09:57:31 +0100695 if (ide_id_has_flush_cache(drive->id)) {
696 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100697 args.tf.feature = arg ?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100699 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100700 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100701 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100702 if (err == 0)
703 drive->wcache = arg;
704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Tejun Heo3e087b52006-01-06 09:57:31 +0100706 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Tejun Heo3e087b52006-01-06 09:57:31 +0100708 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709}
710
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200711static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
713 ide_task_t args;
714
715 memset(&args, 0, sizeof(ide_task_t));
716 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100717 args.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 else
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100719 args.tf.command = WIN_FLUSH_CACHE;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100720 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100721 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722}
723
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200724static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725{
726 ide_task_t args;
727
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200728 if (arg < 0 || arg > 254)
729 return -EINVAL;
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100732 args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
733 args.tf.nsect = arg;
734 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100735 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100736 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 drive->acoustic = arg;
738 return 0;
739}
740
741/*
742 * drive->addressing:
743 * 0: 28-bit
744 * 1: 48-bit
745 * 2: 48-bit capable doing 28-bit
746 */
747static int set_lba_addressing(ide_drive_t *drive, int arg)
748{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200749 if (arg < 0 || arg > 2)
750 return -EINVAL;
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 drive->addressing = 0;
753
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200754 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return 0;
756
757 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200758 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 drive->addressing = arg;
760 return 0;
761}
762
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200763#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764static void idedisk_add_settings(ide_drive_t *drive)
765{
766 struct hd_driveid *id = drive->id;
767
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200768 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
769 &drive->bios_cyl, NULL);
770 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
771 &drive->bios_head, NULL);
772 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
773 &drive->bios_sect, NULL);
774 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
775 &drive->addressing, set_lba_addressing);
776 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
777 id->max_multsect, 1, 1, &drive->mult_count,
778 set_multcount);
779 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
780 &drive->nowerr, set_nowerr);
781 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
782 &drive->lun, NULL);
783 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
784 &drive->wcache, write_cache);
785 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
786 &drive->acoustic, set_acoustic);
787 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
788 &drive->failures, NULL);
789 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
790 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200792#else
793static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
794#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200796static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200798 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 struct hd_driveid *id = drive->id;
800 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 idedisk_add_settings(drive);
803
804 if (drive->id_read == 0)
805 return;
806
Richard Purdie98109332006-02-03 03:04:55 -0800807 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200809 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200811 if (id->model[0] != 'W' || id->model[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 }
814
815 (void)set_lba_addressing(drive, 1);
816
817 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 int max_s = 2048;
819
820 if (max_s > hwif->rqsize)
821 max_s = hwif->rqsize;
822
823 blk_queue_max_sectors(drive->queue, max_s);
824 }
825
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200826 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
827 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
829 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200830 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 /* limit drive capacity to 137GB if LBA48 cannot be used */
833 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
834 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
835 "%llu sectors (%llu MB)\n",
836 drive->name, (unsigned long long)drive->capacity64,
837 sectors_to_MB(drive->capacity64));
838 drive->capacity64 = 1ULL << 28;
839 }
840
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200841 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200843 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
844 " will be used for accessing sectors "
845 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 } else
847 drive->addressing = 0;
848 }
849
850 /*
851 * if possible, give fdisk access to more of the drive,
852 * by correcting bios_cyls:
853 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200854 capacity = idedisk_capacity(drive);
855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (!drive->forced_geom) {
857
858 if (idedisk_supports_lba48(drive->id)) {
859 /* compatibility */
860 drive->bios_sect = 63;
861 drive->bios_head = 255;
862 }
863
864 if (drive->bios_sect && drive->bios_head) {
865 unsigned int cap0 = capacity; /* truncate to 32 bits */
866 unsigned int cylsz, cyl;
867
868 if (cap0 != capacity)
869 drive->bios_cyl = 65535;
870 else {
871 cylsz = drive->bios_sect * drive->bios_head;
872 cyl = cap0 / cylsz;
873 if (cyl > 65535)
874 cyl = 65535;
875 if (cyl > drive->bios_cyl)
876 drive->bios_cyl = cyl;
877 }
878 }
879 }
880 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
881 drive->name, capacity, sectors_to_MB(capacity));
882
883 /* Only print cache size when it was specified */
884 if (id->buf_size)
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100885 printk(KERN_CONT " w/%dKiB Cache", id->buf_size / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100887 printk(KERN_CONT ", CHS=%d/%d/%d\n",
888 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* write cache enabled? */
891 if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
892 drive->wcache = 1;
893
894 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895}
896
897static void ide_cacheflush_p(ide_drive_t *drive)
898{
899 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
900 return;
901
902 if (do_idedisk_flushcache(drive))
903 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
904}
905
Russell King4031bbe2006-01-06 11:41:00 +0000906static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907{
908 struct ide_disk_obj *idkp = drive->driver_data;
909 struct gendisk *g = idkp->disk;
910
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200911 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 del_gendisk(g);
914
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100915 ide_cacheflush_p(drive);
916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918}
919
920static void ide_disk_release(struct kref *kref)
921{
922 struct ide_disk_obj *idkp = to_ide_disk(kref);
923 ide_drive_t *drive = idkp->drive;
924 struct gendisk *g = idkp->disk;
925
926 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 g->private_data = NULL;
928 put_disk(g);
929 kfree(idkp);
930}
931
Russell King4031bbe2006-01-06 11:41:00 +0000932static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Lee Trager0d2157f2007-06-08 15:14:30 +0200934/*
935 * On HPA drives the capacity needs to be
936 * reinitilized on resume otherwise the disk
937 * can not be used and a hard reset is required
938 */
939static void ide_disk_resume(ide_drive_t *drive)
940{
941 if (idedisk_supports_hpa(drive->id))
942 init_idedisk_capacity(drive);
943}
944
Russell King4031bbe2006-01-06 11:41:00 +0000945static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947#ifdef CONFIG_ALPHA
948 /* On Alpha, halt(8) doesn't actually turn the machine off,
949 it puts you into the sort of firmware monitor. Typically,
950 it's used to boot another kernel image, so it's not much
951 different from reboot(8). Therefore, we don't need to
952 spin down the disk in this case, especially since Alpha
953 firmware doesn't handle disks in standby mode properly.
954 On the other hand, it's reasonably safe to turn the power
955 off when the shutdown process reaches the firmware prompt,
956 as the firmware initialization takes rather long time -
957 at least 10 seconds, which should be sufficient for
958 the disk to expire its write cache. */
959 if (system_state != SYSTEM_POWER_OFF) {
960#else
961 if (system_state == SYSTEM_RESTART) {
962#endif
963 ide_cacheflush_p(drive);
964 return;
965 }
966
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100967 printk(KERN_INFO "Shutdown: %s\n", drive->name);
968
Russell King4031bbe2006-01-06 11:41:00 +0000969 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970}
971
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100974 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200975 .name = "ide-disk",
976 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 },
Russell King4031bbe2006-01-06 11:41:00 +0000978 .probe = ide_disk_probe,
979 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200980 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000981 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 .version = IDEDISK_VERSION,
983 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 .do_request = ide_do_rw_disk,
986 .end_request = ide_end_request,
987 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200988#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200990#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991};
992
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100993static int idedisk_set_doorlock(ide_drive_t *drive, int on)
994{
995 ide_task_t task;
996
997 memset(&task, 0, sizeof(task));
998 task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100999 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001000
1001 return ide_no_data_taskfile(drive, &task);
1002}
1003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004static int idedisk_open(struct inode *inode, struct file *filp)
1005{
1006 struct gendisk *disk = inode->i_bdev->bd_disk;
1007 struct ide_disk_obj *idkp;
1008 ide_drive_t *drive;
1009
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001010 idkp = ide_disk_get(disk);
1011 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return -ENXIO;
1013
1014 drive = idkp->drive;
1015
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001016 idkp->openers++;
1017
1018 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 check_disk_change(inode->i_bdev);
1020 /*
1021 * Ignore the return code from door_lock,
1022 * since the open() has already succeeded,
1023 * and the door_lock is irrelevant at this point.
1024 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001025 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 drive->doorlocking = 0;
1027 }
1028 return 0;
1029}
1030
1031static int idedisk_release(struct inode *inode, struct file *filp)
1032{
1033 struct gendisk *disk = inode->i_bdev->bd_disk;
1034 struct ide_disk_obj *idkp = ide_disk_g(disk);
1035 ide_drive_t *drive = idkp->drive;
1036
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001037 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001039
1040 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001041 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 drive->doorlocking = 0;
1043 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001044
1045 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 ide_disk_put(idkp);
1048
1049 return 0;
1050}
1051
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001052static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1053{
1054 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1055 ide_drive_t *drive = idkp->drive;
1056
1057 geo->heads = drive->bios_head;
1058 geo->sectors = drive->bios_sect;
1059 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1060 return 0;
1061}
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063static int idedisk_ioctl(struct inode *inode, struct file *file,
1064 unsigned int cmd, unsigned long arg)
1065{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001066 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 struct block_device *bdev = inode->i_bdev;
1068 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001069 ide_drive_t *drive = idkp->drive;
1070 int err, (*setfunc)(ide_drive_t *, int);
1071 u8 *val;
1072
1073 switch (cmd) {
1074 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1075 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1076 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1077 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1078 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1079 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1080 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1081 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1082 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1083 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1084 }
1085
1086 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1087
1088read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001089 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001090 spin_lock_irqsave(&ide_lock, flags);
1091 err = *val;
1092 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001093 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001094 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1095
1096set_val:
1097 if (bdev != bdev->bd_contains)
1098 err = -EINVAL;
1099 else {
1100 if (!capable(CAP_SYS_ADMIN))
1101 err = -EACCES;
1102 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001103 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001104 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001105 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001106 }
1107 }
1108 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
1111static int idedisk_media_changed(struct gendisk *disk)
1112{
1113 struct ide_disk_obj *idkp = ide_disk_g(disk);
1114 ide_drive_t *drive = idkp->drive;
1115
1116 /* do not scan partitions twice if this is a removable device */
1117 if (drive->attach) {
1118 drive->attach = 0;
1119 return 0;
1120 }
1121 /* if removable, always assume it was changed */
1122 return drive->removable;
1123}
1124
1125static int idedisk_revalidate_disk(struct gendisk *disk)
1126{
1127 struct ide_disk_obj *idkp = ide_disk_g(disk);
1128 set_capacity(disk, idedisk_capacity(idkp->drive));
1129 return 0;
1130}
1131
1132static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001133 .owner = THIS_MODULE,
1134 .open = idedisk_open,
1135 .release = idedisk_release,
1136 .ioctl = idedisk_ioctl,
1137 .getgeo = idedisk_getgeo,
1138 .media_changed = idedisk_media_changed,
1139 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140};
1141
1142MODULE_DESCRIPTION("ATA DISK Driver");
1143
Russell King4031bbe2006-01-06 11:41:00 +00001144static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145{
1146 struct ide_disk_obj *idkp;
1147 struct gendisk *g;
1148
1149 /* strstr("foo", "") is non-NULL */
1150 if (!strstr("ide-disk", drive->driver_req))
1151 goto failed;
1152 if (!drive->present)
1153 goto failed;
1154 if (drive->media != ide_disk)
1155 goto failed;
1156
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001157 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 if (!idkp)
1159 goto failed;
1160
Christoph Lameter19460892005-06-23 00:08:19 -07001161 g = alloc_disk_node(1 << PARTN_BITS,
Christoph Lameter86b37862005-08-09 19:59:21 -07001162 hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (!g)
1164 goto out_free_idkp;
1165
1166 ide_init_disk(g, drive);
1167
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001168 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 kref_init(&idkp->kref);
1171
1172 idkp->drive = drive;
1173 idkp->driver = &idedisk_driver;
1174 idkp->disk = g;
1175
1176 g->private_data = &idkp->driver;
1177
1178 drive->driver_data = idkp;
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 idedisk_setup(drive);
1181 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1182 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1183 drive->name, drive->head);
1184 drive->attach = 0;
1185 } else
1186 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 g->minors = 1 << PARTN_BITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 g->driverfs_dev = &drive->gendev;
1190 g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
1191 set_capacity(g, idedisk_capacity(drive));
1192 g->fops = &idedisk_ops;
1193 add_disk(g);
1194 return 0;
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196out_free_idkp:
1197 kfree(idkp);
1198failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001199 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001202static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001204 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001207static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001209 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210}
1211
Kay Sievers263756e2005-12-12 18:03:44 +01001212MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213module_init(idedisk_init);
1214module_exit(idedisk_exit);
1215MODULE_LICENSE("GPL");