blob: 2e43ae15fb1b00ae5ab8f20c2064b2e43f8fb998 [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#include <linux/ide.h>
Bartlomiej Zolnierkiewicz3ceca722008-10-10 22:39:27 +020034#include <linux/hdreg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#include <asm/byteorder.h>
37#include <asm/irq.h>
38#include <asm/uaccess.h>
39#include <asm/io.h>
40#include <asm/div64.h>
41
Tejun Heo870d6652008-08-25 19:47:25 +090042#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
Tejun Heo689d6fa2008-08-25 19:56:16 +090043#define IDE_DISK_MINORS (1 << PARTN_BITS)
Tejun Heo870d6652008-08-25 19:47:25 +090044#else
Tejun Heo3e1a7ff2008-08-25 19:56:17 +090045#define IDE_DISK_MINORS 0
Tejun Heo870d6652008-08-25 19:47:25 +090046#endif
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048struct ide_disk_obj {
49 ide_drive_t *drive;
50 ide_driver_t *driver;
51 struct gendisk *disk;
52 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010053 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
Arjan van de Vencf8b8972006-03-23 03:00:45 -080056static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
59
60#define ide_disk_g(disk) \
61 container_of((disk)->private_data, struct ide_disk_obj, driver)
62
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020063static void ide_disk_release(struct kref *);
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
66{
67 struct ide_disk_obj *idkp = NULL;
68
Arjan van de Vencf8b8972006-03-23 03:00:45 -080069 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020071 if (idkp) {
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020072 if (ide_device_get(idkp->drive))
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020073 idkp = NULL;
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020074 else
75 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020076 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080077 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return idkp;
79}
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static void ide_disk_put(struct ide_disk_obj *idkp)
82{
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020083 ide_drive_t *drive = idkp->drive;
84
Arjan van de Vencf8b8972006-03-23 03:00:45 -080085 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 kref_put(&idkp->kref, ide_disk_release);
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020087 ide_device_put(drive);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080088 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089}
90
91/*
92 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
93 * value for this drive (from its reported identification information).
94 *
95 * Returns: 1 if lba_capacity looks sensible
96 * 0 otherwise
97 *
98 * It is called only once for each drive.
99 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200100static int lba_capacity_is_ok(u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101{
102 unsigned long lba_sects, chs_sects, head, tail;
103
Alan Cox6efd9362005-06-27 15:24:22 -0700104 /* No non-LBA info .. so valid! */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200105 if (id[ATA_ID_CYLS] == 0)
Alan Cox6efd9362005-06-27 15:24:22 -0700106 return 1;
107
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200108 lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 /*
111 * The ATA spec tells large drives to return
112 * C/H/S = 16383/16/63 independent of their size.
113 * Some drives can be jumpered to use 15 heads instead of 16.
114 * Some drives can be jumpered to use 4092 cyls instead of 16383.
115 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200116 if ((id[ATA_ID_CYLS] == 16383 ||
117 (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
118 id[ATA_ID_SECTORS] == 63 &&
119 (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200120 (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200123 chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
125 /* perform a rough sanity check on lba_sects: within 10% is OK */
126 if ((lba_sects - chs_sects) < chs_sects/10)
127 return 1;
128
129 /* some drives have the word order reversed */
130 head = ((lba_sects >> 16) & 0xffff);
131 tail = (lba_sects & 0xffff);
132 lba_sects = (head | (tail << 16));
133 if ((lba_sects - chs_sects) < chs_sects/10) {
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200134 *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 return 1; /* lba_capacity is (now) good */
136 }
137
138 return 0; /* lba_capacity value may be bad */
139}
140
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100141static const u8 ide_rw_cmds[] = {
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200142 ATA_CMD_READ_MULTI,
143 ATA_CMD_WRITE_MULTI,
144 ATA_CMD_READ_MULTI_EXT,
145 ATA_CMD_WRITE_MULTI_EXT,
146 ATA_CMD_PIO_READ,
147 ATA_CMD_PIO_WRITE,
148 ATA_CMD_PIO_READ_EXT,
149 ATA_CMD_PIO_WRITE_EXT,
150 ATA_CMD_READ,
151 ATA_CMD_WRITE,
152 ATA_CMD_READ_EXT,
153 ATA_CMD_WRITE_EXT,
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100154};
155
156static const u8 ide_data_phases[] = {
157 TASKFILE_MULTI_IN,
158 TASKFILE_MULTI_OUT,
159 TASKFILE_IN,
160 TASKFILE_OUT,
161 TASKFILE_IN_DMA,
162 TASKFILE_OUT_DMA,
163};
164
165static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
166{
167 u8 index, lba48, write;
168
169 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
170 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
171
172 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200173 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100174 else
175 index = drive->mult_count ? 0 : 4;
176
177 task->tf.command = ide_rw_cmds[index + lba48 + write];
178
179 if (dma)
180 index = 8; /* fixup index */
181
182 task->data_phase = ide_data_phases[index / 2 + write];
183}
184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185/*
186 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
187 * using LBA if supported, or CHS otherwise, to address sectors.
188 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200189static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
190 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191{
192 ide_hwif_t *hwif = HWIF(drive);
193 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100194 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100196 ide_task_t task;
197 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100198 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200200 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 if (block + rq->nr_sectors > 1ULL << 28)
202 dma = 0;
203 else
204 lba48 = 0;
205 }
206
207 if (!dma) {
208 ide_init_sg_cmd(drive, rq);
209 ide_map_sg(drive, rq);
210 }
211
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100212 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200213 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (drive->select.b.lba) {
216 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800217 pr_debug("%s: LBA=0x%012llx\n", drive->name,
218 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100220 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100221 tf->hob_lbal = (u8)(block >> 24);
222 if (sizeof(block) != 4) {
223 tf->hob_lbam = (u8)((u64)block >> 32);
224 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100226
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100227 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100228 tf->lbal = (u8) block;
229 tf->lbam = (u8)(block >> 8);
230 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100231
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100232 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100234 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100235 tf->lbal = block;
236 tf->lbam = block >>= 8;
237 tf->lbah = block >>= 8;
238 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200241 unsigned int sect, head, cyl, track;
242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 track = (int)block / drive->sect;
244 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 head = track % drive->head;
246 cyl = track / drive->head;
247
248 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
249
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100250 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100251 tf->lbal = sect;
252 tf->lbam = cyl;
253 tf->lbah = cyl >> 8;
254 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 }
256
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100257 if (rq_data_dir(rq))
258 task.tf_flags |= IDE_TFLAG_WRITE;
259
260 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100261 if (!dma)
262 hwif->data_phase = task.data_phase;
263 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100264
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100265 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100266
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100267 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100269 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100270 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100271 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100273 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100276 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277}
278
279/*
280 * 268435455 == 137439 MB or 28bit limit
281 * 320173056 == 163929 MB or 48bit addressing
282 * 1073741822 == 549756 MB or 48bit addressing fake drive
283 */
284
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200285static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
286 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
288 ide_hwif_t *hwif = HWIF(drive);
289
290 BUG_ON(drive->blocked);
291
292 if (!blk_fs_request(rq)) {
293 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
294 ide_end_request(drive, 0, 0);
295 return ide_stopped;
296 }
297
Richard Purdie2bfb6462006-03-31 02:31:16 -0800298 ledtrig_ide_activity();
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
301 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800302 (unsigned long long)block, rq->nr_sectors,
303 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
305 if (hwif->rw_disk)
306 hwif->rw_disk(drive, rq);
307
308 return __ide_do_rw_disk(drive, rq, block);
309}
310
311/*
312 * Queries for true maximum capacity of the drive.
313 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
314 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100315static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
317 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100318 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100319 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 /* Create IDE/ATA command request structure */
322 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100323 if (lba48)
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200324 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100325 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200326 tf->command = ATA_CMD_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100327 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100328 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100329 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100330 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100332 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100335 if ((tf->status & 0x01) == 0)
336 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 return addr;
339}
340
341/*
342 * Sets maximum virtual LBA address of the drive.
343 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
344 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100345static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
347 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100348 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100349 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 addr_req--;
352 /* Create IDE/ATA command request structure */
353 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100354 tf->lbal = (addr_req >> 0) & 0xff;
355 tf->lbam = (addr_req >>= 8) & 0xff;
356 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100357 if (lba48) {
358 tf->hob_lbal = (addr_req >>= 8) & 0xff;
359 tf->hob_lbam = (addr_req >>= 8) & 0xff;
360 tf->hob_lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200361 tf->command = ATA_CMD_SET_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100362 } else {
363 tf->device = (addr_req >>= 8) & 0x0f;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200364 tf->command = ATA_CMD_SET_MAX;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100365 }
366 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100367 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100368 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100369 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100371 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100373 if ((tf->status & 0x01) == 0)
374 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100375
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 return addr_set;
377}
378
379static unsigned long long sectors_to_MB(unsigned long long n)
380{
381 n <<= 9; /* make it bytes */
382 do_div(n, 1000000); /* make it MB */
383 return n;
384}
385
386/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 * The same here.
388 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200389static inline int idedisk_supports_lba48(const u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200391 return (id[ATA_ID_COMMAND_SET_2] & 0x0400) &&
392 (id[ATA_ID_CFS_ENABLE_2] & 0x0400) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200393 ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394}
395
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200396/*
397 * Some disks report total number of sectors instead of
398 * maximum sector address. We list them here.
399 */
400static const struct drive_list_entry hpa_list[] = {
401 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200402 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100403 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200404 { NULL, NULL }
405};
406
Arjan van de Ven858119e2006-01-14 13:20:43 -0800407static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
409 unsigned long long capacity, set_max;
410 int lba48 = idedisk_supports_lba48(drive->id);
411
412 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100413
414 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200416 if (ide_in_drive_list(drive->id, hpa_list)) {
417 /*
418 * Since we are inclusive wrt to firmware revisions do this
419 * extra check and apply the workaround only when needed.
420 */
421 if (set_max == capacity + 1)
422 set_max--;
423 }
424
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 if (set_max <= capacity)
426 return;
427
428 printk(KERN_INFO "%s: Host Protected Area detected.\n"
429 "\tcurrent capacity is %llu sectors (%llu MB)\n"
430 "\tnative capacity is %llu sectors (%llu MB)\n",
431 drive->name,
432 capacity, sectors_to_MB(capacity),
433 set_max, sectors_to_MB(set_max));
434
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100435 set_max = idedisk_set_max_address(drive, set_max, lba48);
436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 if (set_max) {
438 drive->capacity64 = set_max;
439 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
440 drive->name);
441 }
442}
443
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200444static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200446 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 /*
448 * If this drive supports the Host Protected Area feature set,
449 * then we may need to change our opinion about the drive's capacity.
450 */
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200451 int hpa = ata_id_hpa_enabled(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 if (idedisk_supports_lba48(id)) {
454 /* drive speaks 48-bit LBA */
455 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200456 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 if (hpa)
458 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200459 } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 /* drive speaks 28-bit LBA */
461 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200462 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 if (hpa)
464 idedisk_check_hpa(drive);
465 } else {
466 /* drive speaks boring old 28-bit CHS */
467 drive->capacity64 = drive->cyl * drive->head * drive->sect;
468 }
469}
470
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200471static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Bartlomiej Zolnierkiewicz3c619ff2008-10-10 22:39:22 +0200473 return drive->capacity64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
475
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200476#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477static int smart_enable(ide_drive_t *drive)
478{
479 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100480 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200483 tf->feature = ATA_SMART_ENABLE;
484 tf->lbam = ATA_SMART_LBAM_PASS;
485 tf->lbah = ATA_SMART_LBAH_PASS;
486 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100487 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100488 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489}
490
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200491static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492{
493 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100494 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100497 tf->feature = sub_cmd;
498 tf->nsect = 0x01;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200499 tf->lbam = ATA_SMART_LBAM_PASS;
500 tf->lbah = ATA_SMART_LBAH_PASS;
501 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100502 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100503 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100505 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506}
507
508static int proc_idedisk_read_cache
509 (char *page, char **start, off_t off, int count, int *eof, void *data)
510{
511 ide_drive_t *drive = (ide_drive_t *) data;
512 char *out = page;
513 int len;
514
515 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200516 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200518 len = sprintf(out, "(none)\n");
519
520 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521}
522
523static int proc_idedisk_read_capacity
524 (char *page, char **start, off_t off, int count, int *eof, void *data)
525{
526 ide_drive_t*drive = (ide_drive_t *)data;
527 int len;
528
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200529 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
530
531 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200534static int proc_idedisk_read_smart(char *page, char **start, off_t off,
535 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
537 ide_drive_t *drive = (ide_drive_t *)data;
538 int len = 0, i = 0;
539
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200540 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 unsigned short *val = (unsigned short *) page;
542 char *out = ((char *)val) + (SECTOR_WORDS * 4);
543 page = out;
544 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200545 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
546 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 val += 1;
548 } while (i < (SECTOR_WORDS * 2));
549 len = out - page;
550 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200551
552 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553}
554
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200555static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 (char *page, char **start, off_t off, int count, int *eof, void *data)
557{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200558 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200559 ATA_SMART_READ_VALUES);
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200560}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200562static int proc_idedisk_read_st
563 (char *page, char **start, off_t off, int count, int *eof, void *data)
564{
565 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200566 ATA_SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567}
568
569static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200570 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
571 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
572 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
573 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
574 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 { NULL, 0, NULL, NULL }
576};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200577#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Jens Axboe165125e2007-07-24 09:28:11 +0200579static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100582 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100584 /* FIXME: map struct ide_taskfile on rq->cmd[] */
585 BUG_ON(task == NULL);
586
587 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (ide_id_has_flush_cache_ext(drive->id) &&
589 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200590 task->tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200592 task->tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100593 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
594 IDE_TFLAG_DYN;
595 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100597 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200598 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100599 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600}
601
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200602ide_devset_get(multcount, mult_count);
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604/*
605 * This is tightly woven into the driver->do_special can not touch.
606 * DON'T do it again until a total personality rewrite is committed.
607 */
608static int set_multcount(ide_drive_t *drive, int arg)
609{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200610 struct request *rq;
611 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200613 if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200614 return -EINVAL;
615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (drive->special.b.set_multmode)
617 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100618
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200619 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
620 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 drive->mult_req = arg;
623 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200624 error = blk_execute_rq(drive->queue, NULL, rq, 0);
625 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200626
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 return (drive->mult_count == arg) ? 0 : -EIO;
628}
629
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200630ide_devset_get(nowerr, nowerr);
631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632static int set_nowerr(ide_drive_t *drive, int arg)
633{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200634 if (arg < 0 || arg > 1)
635 return -EINVAL;
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if (ide_spin_wait_hwgroup(drive))
638 return -EBUSY;
639 drive->nowerr = arg;
640 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
641 spin_unlock_irq(&ide_lock);
642 return 0;
643}
644
Tejun Heo3e087b52006-01-06 09:57:31 +0100645static void update_ordered(ide_drive_t *drive)
646{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200647 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100648 unsigned ordered = QUEUE_ORDERED_NONE;
649 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100650
651 if (drive->wcache) {
652 unsigned long long capacity;
653 int barrier;
654 /*
655 * We must avoid issuing commands a drive does not
656 * understand or we may crash it. We check flush cache
657 * is supported. We also check we have the LBA48 flush
658 * cache if the drive capacity is too large. By this
659 * time we have trimmed the drive capacity if LBA48 is
660 * not available so we don't need to recheck that.
661 */
662 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200663 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100664 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
665 ide_id_has_flush_cache_ext(id));
666
667 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800668 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100669
670 if (barrier) {
671 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
672 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100673 }
674 } else
675 ordered = QUEUE_ORDERED_DRAIN;
676
677 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100678}
679
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200680ide_devset_get(wcache, wcache);
681
682static int set_wcache(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
684 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100685 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200687 if (arg < 0 || arg > 1)
688 return -EINVAL;
689
Tejun Heo3e087b52006-01-06 09:57:31 +0100690 if (ide_id_has_flush_cache(drive->id)) {
691 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100692 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200693 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
694 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100695 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100696 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100697 if (err == 0)
698 drive->wcache = arg;
699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
Tejun Heo3e087b52006-01-06 09:57:31 +0100701 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Tejun Heo3e087b52006-01-06 09:57:31 +0100703 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704}
705
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200706static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
708 ide_task_t args;
709
710 memset(&args, 0, sizeof(ide_task_t));
711 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200712 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200714 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100715 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100716 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717}
718
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200719ide_devset_get(acoustic, acoustic);
720
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200721static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722{
723 ide_task_t args;
724
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200725 if (arg < 0 || arg > 254)
726 return -EINVAL;
727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200729 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100730 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200731 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100732 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100733 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 drive->acoustic = arg;
735 return 0;
736}
737
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200738ide_devset_get(lba_addressing, addressing);
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740/*
741 * drive->addressing:
742 * 0: 28-bit
743 * 1: 48-bit
744 * 2: 48-bit capable doing 28-bit
745 */
746static int set_lba_addressing(ide_drive_t *drive, int arg)
747{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200748 if (arg < 0 || arg > 2)
749 return -EINVAL;
750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 drive->addressing = 0;
752
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200753 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return 0;
755
756 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200757 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 drive->addressing = arg;
759 return 0;
760}
761
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200762#ifdef CONFIG_IDE_PROC_FS
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200763ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
764ide_devset_rw_nolock(address, 0, 2, lba_addressing);
765ide_devset_rw_nolock(multcount, 0, 16, multcount);
766ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
767ide_devset_rw_nolock(wcache, 0, 1, wcache);
768
769ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
770ide_devset_rw(bios_head, 0, 255, bios_head);
771ide_devset_rw(bios_sect, 0, 63, bios_sect);
772ide_devset_rw(failures, 0, 65535, failures);
773ide_devset_rw(lun, 0, 7, lun);
774ide_devset_rw(max_failures, 0, 65535, max_failures);
775
776static const struct ide_devset *idedisk_settings[] = {
777 &ide_devset_acoustic,
778 &ide_devset_address,
779 &ide_devset_bios_cyl,
780 &ide_devset_bios_head,
781 &ide_devset_bios_sect,
782 &ide_devset_failures,
783 &ide_devset_lun,
784 &ide_devset_max_failures,
785 &ide_devset_multcount,
786 &ide_devset_nowerr,
787 &ide_devset_wcache,
788 NULL
789};
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200790#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200792static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200794 struct ide_disk_obj *idkp = drive->driver_data;
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200795 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200796 u16 *id = drive->id;
797 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200800 ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 if (drive->id_read == 0)
803 return;
804
Richard Purdie98109332006-02-03 03:04:55 -0800805 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200807 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200809 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 }
812
813 (void)set_lba_addressing(drive, 1);
814
815 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 int max_s = 2048;
817
818 if (max_s > hwif->rqsize)
819 max_s = hwif->rqsize;
820
821 blk_queue_max_sectors(drive->queue, max_s);
822 }
823
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200824 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
825 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
827 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200828 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
830 /* limit drive capacity to 137GB if LBA48 cannot be used */
831 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
832 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
833 "%llu sectors (%llu MB)\n",
834 drive->name, (unsigned long long)drive->capacity64,
835 sectors_to_MB(drive->capacity64));
836 drive->capacity64 = 1ULL << 28;
837 }
838
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200839 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200841 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
842 " will be used for accessing sectors "
843 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 } else
845 drive->addressing = 0;
846 }
847
848 /*
849 * if possible, give fdisk access to more of the drive,
850 * by correcting bios_cyls:
851 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200852 capacity = idedisk_capacity(drive);
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 if (!drive->forced_geom) {
855
856 if (idedisk_supports_lba48(drive->id)) {
857 /* compatibility */
858 drive->bios_sect = 63;
859 drive->bios_head = 255;
860 }
861
862 if (drive->bios_sect && drive->bios_head) {
863 unsigned int cap0 = capacity; /* truncate to 32 bits */
864 unsigned int cylsz, cyl;
865
866 if (cap0 != capacity)
867 drive->bios_cyl = 65535;
868 else {
869 cylsz = drive->bios_sect * drive->bios_head;
870 cyl = cap0 / cylsz;
871 if (cyl > 65535)
872 cyl = 65535;
873 if (cyl > drive->bios_cyl)
874 drive->bios_cyl = cyl;
875 }
876 }
877 }
878 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
879 drive->name, capacity, sectors_to_MB(capacity));
880
881 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200882 if (id[ATA_ID_BUF_SIZE])
883 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100885 printk(KERN_CONT ", CHS=%d/%d/%d\n",
886 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200889 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 drive->wcache = 1;
891
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200892 set_wcache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893}
894
895static void ide_cacheflush_p(ide_drive_t *drive)
896{
897 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
898 return;
899
900 if (do_idedisk_flushcache(drive))
901 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
902}
903
Russell King4031bbe2006-01-06 11:41:00 +0000904static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
906 struct ide_disk_obj *idkp = drive->driver_data;
907 struct gendisk *g = idkp->disk;
908
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200909 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 del_gendisk(g);
912
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100913 ide_cacheflush_p(drive);
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916}
917
918static void ide_disk_release(struct kref *kref)
919{
920 struct ide_disk_obj *idkp = to_ide_disk(kref);
921 ide_drive_t *drive = idkp->drive;
922 struct gendisk *g = idkp->disk;
923
924 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 g->private_data = NULL;
926 put_disk(g);
927 kfree(idkp);
928}
929
Russell King4031bbe2006-01-06 11:41:00 +0000930static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
Lee Trager0d2157f2007-06-08 15:14:30 +0200932/*
933 * On HPA drives the capacity needs to be
934 * reinitilized on resume otherwise the disk
935 * can not be used and a hard reset is required
936 */
937static void ide_disk_resume(ide_drive_t *drive)
938{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200939 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200940 init_idedisk_capacity(drive);
941}
942
Russell King4031bbe2006-01-06 11:41:00 +0000943static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945#ifdef CONFIG_ALPHA
946 /* On Alpha, halt(8) doesn't actually turn the machine off,
947 it puts you into the sort of firmware monitor. Typically,
948 it's used to boot another kernel image, so it's not much
949 different from reboot(8). Therefore, we don't need to
950 spin down the disk in this case, especially since Alpha
951 firmware doesn't handle disks in standby mode properly.
952 On the other hand, it's reasonably safe to turn the power
953 off when the shutdown process reaches the firmware prompt,
954 as the firmware initialization takes rather long time -
955 at least 10 seconds, which should be sufficient for
956 the disk to expire its write cache. */
957 if (system_state != SYSTEM_POWER_OFF) {
958#else
959 if (system_state == SYSTEM_RESTART) {
960#endif
961 ide_cacheflush_p(drive);
962 return;
963 }
964
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100965 printk(KERN_INFO "Shutdown: %s\n", drive->name);
966
Russell King4031bbe2006-01-06 11:41:00 +0000967 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100972 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200973 .name = "ide-disk",
974 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 },
Russell King4031bbe2006-01-06 11:41:00 +0000976 .probe = ide_disk_probe,
977 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200978 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000979 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 .version = IDEDISK_VERSION,
981 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 .do_request = ide_do_rw_disk,
984 .end_request = ide_end_request,
985 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200986#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200988 .settings = idedisk_settings,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200989#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990};
991
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100992static int idedisk_set_doorlock(ide_drive_t *drive, int on)
993{
994 ide_task_t task;
995
996 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200997 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100998 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100999
1000 return ide_no_data_taskfile(drive, &task);
1001}
1002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003static int idedisk_open(struct inode *inode, struct file *filp)
1004{
1005 struct gendisk *disk = inode->i_bdev->bd_disk;
1006 struct ide_disk_obj *idkp;
1007 ide_drive_t *drive;
1008
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001009 idkp = ide_disk_get(disk);
1010 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return -ENXIO;
1012
1013 drive = idkp->drive;
1014
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001015 idkp->openers++;
1016
1017 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 check_disk_change(inode->i_bdev);
1019 /*
1020 * Ignore the return code from door_lock,
1021 * since the open() has already succeeded,
1022 * and the door_lock is irrelevant at this point.
1023 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001024 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 drive->doorlocking = 0;
1026 }
1027 return 0;
1028}
1029
1030static int idedisk_release(struct inode *inode, struct file *filp)
1031{
1032 struct gendisk *disk = inode->i_bdev->bd_disk;
1033 struct ide_disk_obj *idkp = ide_disk_g(disk);
1034 ide_drive_t *drive = idkp->drive;
1035
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001036 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001038
1039 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001040 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 drive->doorlocking = 0;
1042 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001043
1044 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 ide_disk_put(idkp);
1047
1048 return 0;
1049}
1050
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001051static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1052{
1053 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1054 ide_drive_t *drive = idkp->drive;
1055
1056 geo->heads = drive->bios_head;
1057 geo->sectors = drive->bios_sect;
1058 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1059 return 0;
1060}
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062static int idedisk_ioctl(struct inode *inode, struct file *file,
1063 unsigned int cmd, unsigned long arg)
1064{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001065 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 struct block_device *bdev = inode->i_bdev;
1067 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001068 ide_drive_t *drive = idkp->drive;
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001069 int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001070
1071 switch (cmd) {
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001072 case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
1073 case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
1074 case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
1075 case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
1076 case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001077 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1078 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1079 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001080 case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001081 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1082 }
1083
1084 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1085
1086read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001087 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001088 spin_lock_irqsave(&ide_lock, flags);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001089 err = getfunc(drive);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001090 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001091 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001092 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1093
1094set_val:
1095 if (bdev != bdev->bd_contains)
1096 err = -EINVAL;
1097 else {
1098 if (!capable(CAP_SYS_ADMIN))
1099 err = -EACCES;
1100 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001101 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001102 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001103 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001104 }
1105 }
1106 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
1109static int idedisk_media_changed(struct gendisk *disk)
1110{
1111 struct ide_disk_obj *idkp = ide_disk_g(disk);
1112 ide_drive_t *drive = idkp->drive;
1113
1114 /* do not scan partitions twice if this is a removable device */
1115 if (drive->attach) {
1116 drive->attach = 0;
1117 return 0;
1118 }
1119 /* if removable, always assume it was changed */
1120 return drive->removable;
1121}
1122
1123static int idedisk_revalidate_disk(struct gendisk *disk)
1124{
1125 struct ide_disk_obj *idkp = ide_disk_g(disk);
1126 set_capacity(disk, idedisk_capacity(idkp->drive));
1127 return 0;
1128}
1129
1130static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001131 .owner = THIS_MODULE,
1132 .open = idedisk_open,
1133 .release = idedisk_release,
1134 .ioctl = idedisk_ioctl,
1135 .getgeo = idedisk_getgeo,
1136 .media_changed = idedisk_media_changed,
1137 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138};
1139
1140MODULE_DESCRIPTION("ATA DISK Driver");
1141
Russell King4031bbe2006-01-06 11:41:00 +00001142static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143{
1144 struct ide_disk_obj *idkp;
1145 struct gendisk *g;
1146
1147 /* strstr("foo", "") is non-NULL */
1148 if (!strstr("ide-disk", drive->driver_req))
1149 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (drive->media != ide_disk)
1152 goto failed;
1153
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001154 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 if (!idkp)
1156 goto failed;
1157
Tejun Heo689d6fa2008-08-25 19:56:16 +09001158 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 if (!g)
1160 goto out_free_idkp;
1161
1162 ide_init_disk(g, drive);
1163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 kref_init(&idkp->kref);
1165
1166 idkp->drive = drive;
1167 idkp->driver = &idedisk_driver;
1168 idkp->disk = g;
1169
1170 g->private_data = &idkp->driver;
1171
1172 drive->driver_data = idkp;
1173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 idedisk_setup(drive);
1175 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1176 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1177 drive->name, drive->head);
1178 drive->attach = 0;
1179 } else
1180 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001181
Tejun Heof615b482008-08-25 19:47:24 +09001182 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001184 g->flags |= GENHD_FL_EXT_DEVT;
1185 if (drive->removable)
1186 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 set_capacity(g, idedisk_capacity(drive));
1188 g->fops = &idedisk_ops;
1189 add_disk(g);
1190 return 0;
1191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192out_free_idkp:
1193 kfree(idkp);
1194failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001195 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196}
1197
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001198static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001200 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001203static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001205 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
Kay Sievers263756e2005-12-12 18:03:44 +01001208MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209module_init(idedisk_init);
1210module_exit(idedisk_exit);
1211MODULE_LICENSE("GPL");