blob: 28d85b410f7ce03361ddec4c957c930a9aa08518 [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
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020059static void ide_disk_release(struct kref *);
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
62{
63 struct ide_disk_obj *idkp = NULL;
64
Arjan van de Vencf8b8972006-03-23 03:00:45 -080065 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020067 if (idkp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020069 if (ide_device_get(idkp->drive)) {
70 kref_put(&idkp->kref, ide_disk_release);
71 idkp = NULL;
72 }
73 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080074 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 return idkp;
76}
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078static void ide_disk_put(struct ide_disk_obj *idkp)
79{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080080 mutex_lock(&idedisk_ref_mutex);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020081 ide_device_put(idkp->drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 kref_put(&idkp->kref, ide_disk_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080083 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070084}
85
86/*
87 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
88 * value for this drive (from its reported identification information).
89 *
90 * Returns: 1 if lba_capacity looks sensible
91 * 0 otherwise
92 *
93 * It is called only once for each drive.
94 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +020095static int lba_capacity_is_ok(struct hd_driveid *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
97 unsigned long lba_sects, chs_sects, head, tail;
98
Alan Cox6efd9362005-06-27 15:24:22 -070099 /* No non-LBA info .. so valid! */
100 if (id->cyls == 0)
101 return 1;
102
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 /*
104 * The ATA spec tells large drives to return
105 * C/H/S = 16383/16/63 independent of their size.
106 * Some drives can be jumpered to use 15 heads instead of 16.
107 * Some drives can be jumpered to use 4092 cyls instead of 16383.
108 */
109 if ((id->cyls == 16383
110 || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
111 id->sectors == 63 &&
112 (id->heads == 15 || id->heads == 16) &&
113 (id->lba_capacity >= 16383*63*id->heads))
114 return 1;
115
116 lba_sects = id->lba_capacity;
117 chs_sects = id->cyls * id->heads * id->sectors;
118
119 /* perform a rough sanity check on lba_sects: within 10% is OK */
120 if ((lba_sects - chs_sects) < chs_sects/10)
121 return 1;
122
123 /* some drives have the word order reversed */
124 head = ((lba_sects >> 16) & 0xffff);
125 tail = (lba_sects & 0xffff);
126 lba_sects = (head | (tail << 16));
127 if ((lba_sects - chs_sects) < chs_sects/10) {
128 id->lba_capacity = lba_sects;
129 return 1; /* lba_capacity is (now) good */
130 }
131
132 return 0; /* lba_capacity value may be bad */
133}
134
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100135static const u8 ide_rw_cmds[] = {
136 WIN_MULTREAD,
137 WIN_MULTWRITE,
138 WIN_MULTREAD_EXT,
139 WIN_MULTWRITE_EXT,
140 WIN_READ,
141 WIN_WRITE,
142 WIN_READ_EXT,
143 WIN_WRITE_EXT,
144 WIN_READDMA,
145 WIN_WRITEDMA,
146 WIN_READDMA_EXT,
147 WIN_WRITEDMA_EXT,
148};
149
150static const u8 ide_data_phases[] = {
151 TASKFILE_MULTI_IN,
152 TASKFILE_MULTI_OUT,
153 TASKFILE_IN,
154 TASKFILE_OUT,
155 TASKFILE_IN_DMA,
156 TASKFILE_OUT_DMA,
157};
158
159static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
160{
161 u8 index, lba48, write;
162
163 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
164 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
165
166 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200167 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100168 else
169 index = drive->mult_count ? 0 : 4;
170
171 task->tf.command = ide_rw_cmds[index + lba48 + write];
172
173 if (dma)
174 index = 8; /* fixup index */
175
176 task->data_phase = ide_data_phases[index / 2 + write];
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/*
180 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
181 * using LBA if supported, or CHS otherwise, to address sectors.
182 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200183static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
184 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
186 ide_hwif_t *hwif = HWIF(drive);
187 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100188 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100190 ide_task_t task;
191 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100192 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200194 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 if (block + rq->nr_sectors > 1ULL << 28)
196 dma = 0;
197 else
198 lba48 = 0;
199 }
200
201 if (!dma) {
202 ide_init_sg_cmd(drive, rq);
203 ide_map_sg(drive, rq);
204 }
205
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100206 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200207 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 if (drive->select.b.lba) {
210 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800211 pr_debug("%s: LBA=0x%012llx\n", drive->name,
212 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100214 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100215 tf->hob_lbal = (u8)(block >> 24);
216 if (sizeof(block) != 4) {
217 tf->hob_lbam = (u8)((u64)block >> 32);
218 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100220
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100221 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100222 tf->lbal = (u8) block;
223 tf->lbam = (u8)(block >> 8);
224 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100225
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100226 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100228 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100229 tf->lbal = block;
230 tf->lbam = block >>= 8;
231 tf->lbah = block >>= 8;
232 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
234 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200235 unsigned int sect, head, cyl, track;
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 track = (int)block / drive->sect;
238 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 head = track % drive->head;
240 cyl = track / drive->head;
241
242 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
243
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100244 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100245 tf->lbal = sect;
246 tf->lbam = cyl;
247 tf->lbah = cyl >> 8;
248 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
250
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100251 if (rq_data_dir(rq))
252 task.tf_flags |= IDE_TFLAG_WRITE;
253
254 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100255 if (!dma)
256 hwif->data_phase = task.data_phase;
257 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100258
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100259 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100260
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100261 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100263 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100264 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100265 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100267 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100270 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271}
272
273/*
274 * 268435455 == 137439 MB or 28bit limit
275 * 320173056 == 163929 MB or 48bit addressing
276 * 1073741822 == 549756 MB or 48bit addressing fake drive
277 */
278
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200279static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
280 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 ide_hwif_t *hwif = HWIF(drive);
283
284 BUG_ON(drive->blocked);
285
286 if (!blk_fs_request(rq)) {
287 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
288 ide_end_request(drive, 0, 0);
289 return ide_stopped;
290 }
291
Richard Purdie2bfb6462006-03-31 02:31:16 -0800292 ledtrig_ide_activity();
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
295 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800296 (unsigned long long)block, rq->nr_sectors,
297 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299 if (hwif->rw_disk)
300 hwif->rw_disk(drive, rq);
301
302 return __ide_do_rw_disk(drive, rq, block);
303}
304
305/*
306 * Queries for true maximum capacity of the drive.
307 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
308 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100309static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310{
311 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100312 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100313 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
315 /* Create IDE/ATA command request structure */
316 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100317 if (lba48)
318 tf->command = WIN_READ_NATIVE_MAX_EXT;
319 else
320 tf->command = WIN_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100321 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100322 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100323 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100324 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100326 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
328 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100329 if ((tf->status & 0x01) == 0)
330 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 return addr;
333}
334
335/*
336 * Sets maximum virtual LBA address of the drive.
337 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
338 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100339static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340{
341 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100342 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100343 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 addr_req--;
346 /* Create IDE/ATA command request structure */
347 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100348 tf->lbal = (addr_req >> 0) & 0xff;
349 tf->lbam = (addr_req >>= 8) & 0xff;
350 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100351 if (lba48) {
352 tf->hob_lbal = (addr_req >>= 8) & 0xff;
353 tf->hob_lbam = (addr_req >>= 8) & 0xff;
354 tf->hob_lbah = (addr_req >>= 8) & 0xff;
355 tf->command = WIN_SET_MAX_EXT;
356 } else {
357 tf->device = (addr_req >>= 8) & 0x0f;
358 tf->command = WIN_SET_MAX;
359 }
360 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100361 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100362 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100363 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100365 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100367 if ((tf->status & 0x01) == 0)
368 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return addr_set;
371}
372
373static unsigned long long sectors_to_MB(unsigned long long n)
374{
375 n <<= 9; /* make it bytes */
376 do_div(n, 1000000); /* make it MB */
377 return n;
378}
379
380/*
381 * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
382 * so on non-buggy drives we need test only one.
383 * However, we should also check whether these fields are valid.
384 */
385static inline int idedisk_supports_hpa(const struct hd_driveid *id)
386{
387 return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
388}
389
390/*
391 * The same here.
392 */
393static inline int idedisk_supports_lba48(const struct hd_driveid *id)
394{
395 return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)
396 && id->lba_capacity_2;
397}
398
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200399/*
400 * Some disks report total number of sectors instead of
401 * maximum sector address. We list them here.
402 */
403static const struct drive_list_entry hpa_list[] = {
404 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200405 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100406 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200407 { NULL, NULL }
408};
409
Arjan van de Ven858119e2006-01-14 13:20:43 -0800410static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
412 unsigned long long capacity, set_max;
413 int lba48 = idedisk_supports_lba48(drive->id);
414
415 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100416
417 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200419 if (ide_in_drive_list(drive->id, hpa_list)) {
420 /*
421 * Since we are inclusive wrt to firmware revisions do this
422 * extra check and apply the workaround only when needed.
423 */
424 if (set_max == capacity + 1)
425 set_max--;
426 }
427
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 if (set_max <= capacity)
429 return;
430
431 printk(KERN_INFO "%s: Host Protected Area detected.\n"
432 "\tcurrent capacity is %llu sectors (%llu MB)\n"
433 "\tnative capacity is %llu sectors (%llu MB)\n",
434 drive->name,
435 capacity, sectors_to_MB(capacity),
436 set_max, sectors_to_MB(set_max));
437
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100438 set_max = idedisk_set_max_address(drive, set_max, lba48);
439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 if (set_max) {
441 drive->capacity64 = set_max;
442 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
443 drive->name);
444 }
445}
446
447/*
448 * Compute drive->capacity, the full capacity of the drive
449 * Called with drive->id != NULL.
450 *
451 * To compute capacity, this uses either of
452 *
453 * 1. CHS value set by user (whatever user sets will be trusted)
454 * 2. LBA value from target drive (require new ATA feature)
455 * 3. LBA value from system BIOS (new one is OK, old one may break)
456 * 4. CHS value from system BIOS (traditional style)
457 *
458 * in above order (i.e., if value of higher priority is available,
459 * reset will be ignored).
460 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200461static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
463 struct hd_driveid *id = drive->id;
464 /*
465 * If this drive supports the Host Protected Area feature set,
466 * then we may need to change our opinion about the drive's capacity.
467 */
468 int hpa = idedisk_supports_hpa(id);
469
470 if (idedisk_supports_lba48(id)) {
471 /* drive speaks 48-bit LBA */
472 drive->select.b.lba = 1;
473 drive->capacity64 = id->lba_capacity_2;
474 if (hpa)
475 idedisk_check_hpa(drive);
476 } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
477 /* drive speaks 28-bit LBA */
478 drive->select.b.lba = 1;
479 drive->capacity64 = id->lba_capacity;
480 if (hpa)
481 idedisk_check_hpa(drive);
482 } else {
483 /* drive speaks boring old 28-bit CHS */
484 drive->capacity64 = drive->cyl * drive->head * drive->sect;
485 }
486}
487
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200488static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 return drive->capacity64 - drive->sect0;
491}
492
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200493#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494static int smart_enable(ide_drive_t *drive)
495{
496 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100497 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100500 tf->feature = SMART_ENABLE;
501 tf->lbam = SMART_LCYL_PASS;
502 tf->lbah = SMART_HCYL_PASS;
503 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100504 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100505 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506}
507
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200508static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509{
510 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100511 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100514 tf->feature = sub_cmd;
515 tf->nsect = 0x01;
516 tf->lbam = SMART_LCYL_PASS;
517 tf->lbah = SMART_HCYL_PASS;
518 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100519 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100520 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100522 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523}
524
525static int proc_idedisk_read_cache
526 (char *page, char **start, off_t off, int count, int *eof, void *data)
527{
528 ide_drive_t *drive = (ide_drive_t *) data;
529 char *out = page;
530 int len;
531
532 if (drive->id_read)
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200533 len = sprintf(out, "%i\n", drive->id->buf_size / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200535 len = sprintf(out, "(none)\n");
536
537 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538}
539
540static int proc_idedisk_read_capacity
541 (char *page, char **start, off_t off, int count, int *eof, void *data)
542{
543 ide_drive_t*drive = (ide_drive_t *)data;
544 int len;
545
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200546 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
547
548 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549}
550
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200551static int proc_idedisk_read_smart(char *page, char **start, off_t off,
552 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 ide_drive_t *drive = (ide_drive_t *)data;
555 int len = 0, i = 0;
556
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200557 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 unsigned short *val = (unsigned short *) page;
559 char *out = ((char *)val) + (SECTOR_WORDS * 4);
560 page = out;
561 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200562 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
563 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 val += 1;
565 } while (i < (SECTOR_WORDS * 2));
566 len = out - page;
567 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200568
569 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570}
571
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200572static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 (char *page, char **start, off_t off, int count, int *eof, void *data)
574{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200575 return proc_idedisk_read_smart(page, start, off, count, eof, data,
576 SMART_READ_VALUES);
577}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200579static int proc_idedisk_read_st
580 (char *page, char **start, off_t off, int count, int *eof, void *data)
581{
582 return proc_idedisk_read_smart(page, start, off, count, eof, data,
583 SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584}
585
586static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200587 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
588 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
589 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
590 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
591 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 { NULL, 0, NULL, NULL }
593};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200594#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Jens Axboe165125e2007-07-24 09:28:11 +0200596static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597{
598 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100599 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100601 /* FIXME: map struct ide_taskfile on rq->cmd[] */
602 BUG_ON(task == NULL);
603
604 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 if (ide_id_has_flush_cache_ext(drive->id) &&
606 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100607 task->tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 else
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100609 task->tf.command = WIN_FLUSH_CACHE;
610 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
611 IDE_TFLAG_DYN;
612 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100614 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200615 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100616 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617}
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619/*
620 * This is tightly woven into the driver->do_special can not touch.
621 * DON'T do it again until a total personality rewrite is committed.
622 */
623static int set_multcount(ide_drive_t *drive, int arg)
624{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200625 struct request *rq;
626 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200628 if (arg < 0 || arg > drive->id->max_multsect)
629 return -EINVAL;
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 if (drive->special.b.set_multmode)
632 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100633
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200634 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
635 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 drive->mult_req = arg;
638 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200639 error = blk_execute_rq(drive->queue, NULL, rq, 0);
640 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200641
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 return (drive->mult_count == arg) ? 0 : -EIO;
643}
644
645static int set_nowerr(ide_drive_t *drive, int arg)
646{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200647 if (arg < 0 || arg > 1)
648 return -EINVAL;
649
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 if (ide_spin_wait_hwgroup(drive))
651 return -EBUSY;
652 drive->nowerr = arg;
653 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
654 spin_unlock_irq(&ide_lock);
655 return 0;
656}
657
Tejun Heo3e087b52006-01-06 09:57:31 +0100658static void update_ordered(ide_drive_t *drive)
659{
660 struct hd_driveid *id = drive->id;
661 unsigned ordered = QUEUE_ORDERED_NONE;
662 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100663
664 if (drive->wcache) {
665 unsigned long long capacity;
666 int barrier;
667 /*
668 * We must avoid issuing commands a drive does not
669 * understand or we may crash it. We check flush cache
670 * is supported. We also check we have the LBA48 flush
671 * cache if the drive capacity is too large. By this
672 * time we have trimmed the drive capacity if LBA48 is
673 * not available so we don't need to recheck that.
674 */
675 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200676 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100677 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
678 ide_id_has_flush_cache_ext(id));
679
680 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800681 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100682
683 if (barrier) {
684 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
685 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100686 }
687 } else
688 ordered = QUEUE_ORDERED_DRAIN;
689
690 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100691}
692
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693static int write_cache(ide_drive_t *drive, int arg)
694{
695 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100696 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200698 if (arg < 0 || arg > 1)
699 return -EINVAL;
700
Tejun Heo3e087b52006-01-06 09:57:31 +0100701 if (ide_id_has_flush_cache(drive->id)) {
702 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100703 args.tf.feature = arg ?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100705 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100706 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100707 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100708 if (err == 0)
709 drive->wcache = arg;
710 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Tejun Heo3e087b52006-01-06 09:57:31 +0100712 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Tejun Heo3e087b52006-01-06 09:57:31 +0100714 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715}
716
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200717static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{
719 ide_task_t args;
720
721 memset(&args, 0, sizeof(ide_task_t));
722 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100723 args.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 else
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100725 args.tf.command = WIN_FLUSH_CACHE;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100726 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100727 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
729
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200730static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{
732 ide_task_t args;
733
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200734 if (arg < 0 || arg > 254)
735 return -EINVAL;
736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100738 args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
739 args.tf.nsect = arg;
740 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100741 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100742 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 drive->acoustic = arg;
744 return 0;
745}
746
747/*
748 * drive->addressing:
749 * 0: 28-bit
750 * 1: 48-bit
751 * 2: 48-bit capable doing 28-bit
752 */
753static int set_lba_addressing(ide_drive_t *drive, int arg)
754{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200755 if (arg < 0 || arg > 2)
756 return -EINVAL;
757
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 drive->addressing = 0;
759
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200760 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 return 0;
762
763 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200764 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 drive->addressing = arg;
766 return 0;
767}
768
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200769#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770static void idedisk_add_settings(ide_drive_t *drive)
771{
772 struct hd_driveid *id = drive->id;
773
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200774 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
775 &drive->bios_cyl, NULL);
776 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
777 &drive->bios_head, NULL);
778 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
779 &drive->bios_sect, NULL);
780 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
781 &drive->addressing, set_lba_addressing);
782 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
783 id->max_multsect, 1, 1, &drive->mult_count,
784 set_multcount);
785 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
786 &drive->nowerr, set_nowerr);
787 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
788 &drive->lun, NULL);
789 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
790 &drive->wcache, write_cache);
791 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
792 &drive->acoustic, set_acoustic);
793 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
794 &drive->failures, NULL);
795 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
796 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200798#else
799static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
800#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200802static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200804 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 struct hd_driveid *id = drive->id;
806 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
808 idedisk_add_settings(drive);
809
810 if (drive->id_read == 0)
811 return;
812
Richard Purdie98109332006-02-03 03:04:55 -0800813 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200815 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200817 if (id->model[0] != 'W' || id->model[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 }
820
821 (void)set_lba_addressing(drive, 1);
822
823 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 int max_s = 2048;
825
826 if (max_s > hwif->rqsize)
827 max_s = hwif->rqsize;
828
829 blk_queue_max_sectors(drive->queue, max_s);
830 }
831
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200832 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
833 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200836 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
838 /* limit drive capacity to 137GB if LBA48 cannot be used */
839 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
840 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
841 "%llu sectors (%llu MB)\n",
842 drive->name, (unsigned long long)drive->capacity64,
843 sectors_to_MB(drive->capacity64));
844 drive->capacity64 = 1ULL << 28;
845 }
846
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200847 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200849 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
850 " will be used for accessing sectors "
851 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 } else
853 drive->addressing = 0;
854 }
855
856 /*
857 * if possible, give fdisk access to more of the drive,
858 * by correcting bios_cyls:
859 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200860 capacity = idedisk_capacity(drive);
861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 if (!drive->forced_geom) {
863
864 if (idedisk_supports_lba48(drive->id)) {
865 /* compatibility */
866 drive->bios_sect = 63;
867 drive->bios_head = 255;
868 }
869
870 if (drive->bios_sect && drive->bios_head) {
871 unsigned int cap0 = capacity; /* truncate to 32 bits */
872 unsigned int cylsz, cyl;
873
874 if (cap0 != capacity)
875 drive->bios_cyl = 65535;
876 else {
877 cylsz = drive->bios_sect * drive->bios_head;
878 cyl = cap0 / cylsz;
879 if (cyl > 65535)
880 cyl = 65535;
881 if (cyl > drive->bios_cyl)
882 drive->bios_cyl = cyl;
883 }
884 }
885 }
886 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
887 drive->name, capacity, sectors_to_MB(capacity));
888
889 /* Only print cache size when it was specified */
890 if (id->buf_size)
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100891 printk(KERN_CONT " w/%dKiB Cache", id->buf_size / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100893 printk(KERN_CONT ", CHS=%d/%d/%d\n",
894 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 /* write cache enabled? */
897 if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
898 drive->wcache = 1;
899
900 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
903static void ide_cacheflush_p(ide_drive_t *drive)
904{
905 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
906 return;
907
908 if (do_idedisk_flushcache(drive))
909 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
910}
911
Russell King4031bbe2006-01-06 11:41:00 +0000912static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913{
914 struct ide_disk_obj *idkp = drive->driver_data;
915 struct gendisk *g = idkp->disk;
916
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200917 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 del_gendisk(g);
920
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100921 ide_cacheflush_p(drive);
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924}
925
926static void ide_disk_release(struct kref *kref)
927{
928 struct ide_disk_obj *idkp = to_ide_disk(kref);
929 ide_drive_t *drive = idkp->drive;
930 struct gendisk *g = idkp->disk;
931
932 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 g->private_data = NULL;
934 put_disk(g);
935 kfree(idkp);
936}
937
Russell King4031bbe2006-01-06 11:41:00 +0000938static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Lee Trager0d2157f2007-06-08 15:14:30 +0200940/*
941 * On HPA drives the capacity needs to be
942 * reinitilized on resume otherwise the disk
943 * can not be used and a hard reset is required
944 */
945static void ide_disk_resume(ide_drive_t *drive)
946{
947 if (idedisk_supports_hpa(drive->id))
948 init_idedisk_capacity(drive);
949}
950
Russell King4031bbe2006-01-06 11:41:00 +0000951static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953#ifdef CONFIG_ALPHA
954 /* On Alpha, halt(8) doesn't actually turn the machine off,
955 it puts you into the sort of firmware monitor. Typically,
956 it's used to boot another kernel image, so it's not much
957 different from reboot(8). Therefore, we don't need to
958 spin down the disk in this case, especially since Alpha
959 firmware doesn't handle disks in standby mode properly.
960 On the other hand, it's reasonably safe to turn the power
961 off when the shutdown process reaches the firmware prompt,
962 as the firmware initialization takes rather long time -
963 at least 10 seconds, which should be sufficient for
964 the disk to expire its write cache. */
965 if (system_state != SYSTEM_POWER_OFF) {
966#else
967 if (system_state == SYSTEM_RESTART) {
968#endif
969 ide_cacheflush_p(drive);
970 return;
971 }
972
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100973 printk(KERN_INFO "Shutdown: %s\n", drive->name);
974
Russell King4031bbe2006-01-06 11:41:00 +0000975 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100980 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200981 .name = "ide-disk",
982 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 },
Russell King4031bbe2006-01-06 11:41:00 +0000984 .probe = ide_disk_probe,
985 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200986 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000987 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 .version = IDEDISK_VERSION,
989 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 .do_request = ide_do_rw_disk,
992 .end_request = ide_end_request,
993 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200994#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200996#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997};
998
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100999static int idedisk_set_doorlock(ide_drive_t *drive, int on)
1000{
1001 ide_task_t task;
1002
1003 memset(&task, 0, sizeof(task));
1004 task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +01001005 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001006
1007 return ide_no_data_taskfile(drive, &task);
1008}
1009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010static int idedisk_open(struct inode *inode, struct file *filp)
1011{
1012 struct gendisk *disk = inode->i_bdev->bd_disk;
1013 struct ide_disk_obj *idkp;
1014 ide_drive_t *drive;
1015
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001016 idkp = ide_disk_get(disk);
1017 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 return -ENXIO;
1019
1020 drive = idkp->drive;
1021
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001022 idkp->openers++;
1023
1024 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 check_disk_change(inode->i_bdev);
1026 /*
1027 * Ignore the return code from door_lock,
1028 * since the open() has already succeeded,
1029 * and the door_lock is irrelevant at this point.
1030 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001031 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 drive->doorlocking = 0;
1033 }
1034 return 0;
1035}
1036
1037static int idedisk_release(struct inode *inode, struct file *filp)
1038{
1039 struct gendisk *disk = inode->i_bdev->bd_disk;
1040 struct ide_disk_obj *idkp = ide_disk_g(disk);
1041 ide_drive_t *drive = idkp->drive;
1042
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001043 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001045
1046 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001047 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 drive->doorlocking = 0;
1049 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001050
1051 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 ide_disk_put(idkp);
1054
1055 return 0;
1056}
1057
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001058static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1059{
1060 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1061 ide_drive_t *drive = idkp->drive;
1062
1063 geo->heads = drive->bios_head;
1064 geo->sectors = drive->bios_sect;
1065 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1066 return 0;
1067}
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069static int idedisk_ioctl(struct inode *inode, struct file *file,
1070 unsigned int cmd, unsigned long arg)
1071{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001072 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 struct block_device *bdev = inode->i_bdev;
1074 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001075 ide_drive_t *drive = idkp->drive;
1076 int err, (*setfunc)(ide_drive_t *, int);
1077 u8 *val;
1078
1079 switch (cmd) {
1080 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1081 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1082 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1083 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1084 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1085 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1086 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1087 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1088 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1089 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1090 }
1091
1092 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1093
1094read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001095 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001096 spin_lock_irqsave(&ide_lock, flags);
1097 err = *val;
1098 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001099 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001100 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1101
1102set_val:
1103 if (bdev != bdev->bd_contains)
1104 err = -EINVAL;
1105 else {
1106 if (!capable(CAP_SYS_ADMIN))
1107 err = -EACCES;
1108 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001109 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001110 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001111 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001112 }
1113 }
1114 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
1116
1117static int idedisk_media_changed(struct gendisk *disk)
1118{
1119 struct ide_disk_obj *idkp = ide_disk_g(disk);
1120 ide_drive_t *drive = idkp->drive;
1121
1122 /* do not scan partitions twice if this is a removable device */
1123 if (drive->attach) {
1124 drive->attach = 0;
1125 return 0;
1126 }
1127 /* if removable, always assume it was changed */
1128 return drive->removable;
1129}
1130
1131static int idedisk_revalidate_disk(struct gendisk *disk)
1132{
1133 struct ide_disk_obj *idkp = ide_disk_g(disk);
1134 set_capacity(disk, idedisk_capacity(idkp->drive));
1135 return 0;
1136}
1137
1138static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001139 .owner = THIS_MODULE,
1140 .open = idedisk_open,
1141 .release = idedisk_release,
1142 .ioctl = idedisk_ioctl,
1143 .getgeo = idedisk_getgeo,
1144 .media_changed = idedisk_media_changed,
1145 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146};
1147
1148MODULE_DESCRIPTION("ATA DISK Driver");
1149
Russell King4031bbe2006-01-06 11:41:00 +00001150static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151{
1152 struct ide_disk_obj *idkp;
1153 struct gendisk *g;
1154
1155 /* strstr("foo", "") is non-NULL */
1156 if (!strstr("ide-disk", drive->driver_req))
1157 goto failed;
1158 if (!drive->present)
1159 goto failed;
1160 if (drive->media != ide_disk)
1161 goto failed;
1162
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001163 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 if (!idkp)
1165 goto failed;
1166
Christoph Lameter19460892005-06-23 00:08:19 -07001167 g = alloc_disk_node(1 << PARTN_BITS,
Christoph Lameter86b37862005-08-09 19:59:21 -07001168 hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 if (!g)
1170 goto out_free_idkp;
1171
1172 ide_init_disk(g, drive);
1173
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001174 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 kref_init(&idkp->kref);
1177
1178 idkp->drive = drive;
1179 idkp->driver = &idedisk_driver;
1180 idkp->disk = g;
1181
1182 g->private_data = &idkp->driver;
1183
1184 drive->driver_data = idkp;
1185
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 idedisk_setup(drive);
1187 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1188 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1189 drive->name, drive->head);
1190 drive->attach = 0;
1191 } else
1192 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001193
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 g->minors = 1 << PARTN_BITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 g->driverfs_dev = &drive->gendev;
1196 g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
1197 set_capacity(g, idedisk_capacity(drive));
1198 g->fops = &idedisk_ops;
1199 add_disk(g);
1200 return 0;
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202out_free_idkp:
1203 kfree(idkp);
1204failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001205 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001208static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001210 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211}
1212
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001213static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001215 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216}
1217
Kay Sievers263756e2005-12-12 18:03:44 +01001218MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219module_init(idedisk_init);
1220module_exit(idedisk_exit);
1221MODULE_LICENSE("GPL");