blob: 5fc4213437a5f42330635316de0f2a70308341d1 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602/*
603 * This is tightly woven into the driver->do_special can not touch.
604 * DON'T do it again until a total personality rewrite is committed.
605 */
606static int set_multcount(ide_drive_t *drive, int arg)
607{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200608 struct request *rq;
609 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200611 if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200612 return -EINVAL;
613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 if (drive->special.b.set_multmode)
615 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100616
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200617 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
618 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 drive->mult_req = arg;
621 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200622 error = blk_execute_rq(drive->queue, NULL, rq, 0);
623 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 return (drive->mult_count == arg) ? 0 : -EIO;
626}
627
628static int set_nowerr(ide_drive_t *drive, int arg)
629{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200630 if (arg < 0 || arg > 1)
631 return -EINVAL;
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (ide_spin_wait_hwgroup(drive))
634 return -EBUSY;
635 drive->nowerr = arg;
636 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
637 spin_unlock_irq(&ide_lock);
638 return 0;
639}
640
Tejun Heo3e087b52006-01-06 09:57:31 +0100641static void update_ordered(ide_drive_t *drive)
642{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200643 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100644 unsigned ordered = QUEUE_ORDERED_NONE;
645 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100646
647 if (drive->wcache) {
648 unsigned long long capacity;
649 int barrier;
650 /*
651 * We must avoid issuing commands a drive does not
652 * understand or we may crash it. We check flush cache
653 * is supported. We also check we have the LBA48 flush
654 * cache if the drive capacity is too large. By this
655 * time we have trimmed the drive capacity if LBA48 is
656 * not available so we don't need to recheck that.
657 */
658 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200659 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100660 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
661 ide_id_has_flush_cache_ext(id));
662
663 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800664 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100665
666 if (barrier) {
667 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
668 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100669 }
670 } else
671 ordered = QUEUE_ORDERED_DRAIN;
672
673 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100674}
675
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676static int write_cache(ide_drive_t *drive, int arg)
677{
678 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100679 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200681 if (arg < 0 || arg > 1)
682 return -EINVAL;
683
Tejun Heo3e087b52006-01-06 09:57:31 +0100684 if (ide_id_has_flush_cache(drive->id)) {
685 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100686 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200687 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
688 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100689 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100690 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100691 if (err == 0)
692 drive->wcache = arg;
693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
Tejun Heo3e087b52006-01-06 09:57:31 +0100695 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Tejun Heo3e087b52006-01-06 09:57:31 +0100697 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200700static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
702 ide_task_t args;
703
704 memset(&args, 0, sizeof(ide_task_t));
705 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200706 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200708 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100709 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100710 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711}
712
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200713static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 ide_task_t args;
716
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200717 if (arg < 0 || arg > 254)
718 return -EINVAL;
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200721 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100722 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200723 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100724 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100725 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 drive->acoustic = arg;
727 return 0;
728}
729
730/*
731 * drive->addressing:
732 * 0: 28-bit
733 * 1: 48-bit
734 * 2: 48-bit capable doing 28-bit
735 */
736static int set_lba_addressing(ide_drive_t *drive, int arg)
737{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200738 if (arg < 0 || arg > 2)
739 return -EINVAL;
740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 drive->addressing = 0;
742
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200743 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return 0;
745
746 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200747 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 drive->addressing = arg;
749 return 0;
750}
751
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200752#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753static void idedisk_add_settings(ide_drive_t *drive)
754{
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200755 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
756 &drive->bios_cyl, NULL);
757 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
758 &drive->bios_head, NULL);
759 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
760 &drive->bios_sect, NULL);
761 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
762 &drive->addressing, set_lba_addressing);
763 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200764 drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1,
765 &drive->mult_count, set_multcount);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200766 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
767 &drive->nowerr, set_nowerr);
768 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
769 &drive->lun, NULL);
770 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
771 &drive->wcache, write_cache);
772 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
773 &drive->acoustic, set_acoustic);
774 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
775 &drive->failures, NULL);
776 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
777 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200779#else
780static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
781#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200783static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200785 struct ide_disk_obj *idkp = drive->driver_data;
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200786 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200787 u16 *id = drive->id;
788 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200791 ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 idedisk_add_settings(drive);
793
794 if (drive->id_read == 0)
795 return;
796
Richard Purdie98109332006-02-03 03:04:55 -0800797 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200799 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200801 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 }
804
805 (void)set_lba_addressing(drive, 1);
806
807 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 int max_s = 2048;
809
810 if (max_s > hwif->rqsize)
811 max_s = hwif->rqsize;
812
813 blk_queue_max_sectors(drive->queue, max_s);
814 }
815
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200816 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
817 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
819 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200820 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 /* limit drive capacity to 137GB if LBA48 cannot be used */
823 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
824 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
825 "%llu sectors (%llu MB)\n",
826 drive->name, (unsigned long long)drive->capacity64,
827 sectors_to_MB(drive->capacity64));
828 drive->capacity64 = 1ULL << 28;
829 }
830
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200831 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200833 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
834 " will be used for accessing sectors "
835 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 } else
837 drive->addressing = 0;
838 }
839
840 /*
841 * if possible, give fdisk access to more of the drive,
842 * by correcting bios_cyls:
843 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200844 capacity = idedisk_capacity(drive);
845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if (!drive->forced_geom) {
847
848 if (idedisk_supports_lba48(drive->id)) {
849 /* compatibility */
850 drive->bios_sect = 63;
851 drive->bios_head = 255;
852 }
853
854 if (drive->bios_sect && drive->bios_head) {
855 unsigned int cap0 = capacity; /* truncate to 32 bits */
856 unsigned int cylsz, cyl;
857
858 if (cap0 != capacity)
859 drive->bios_cyl = 65535;
860 else {
861 cylsz = drive->bios_sect * drive->bios_head;
862 cyl = cap0 / cylsz;
863 if (cyl > 65535)
864 cyl = 65535;
865 if (cyl > drive->bios_cyl)
866 drive->bios_cyl = cyl;
867 }
868 }
869 }
870 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
871 drive->name, capacity, sectors_to_MB(capacity));
872
873 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200874 if (id[ATA_ID_BUF_SIZE])
875 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100877 printk(KERN_CONT ", CHS=%d/%d/%d\n",
878 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200881 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 drive->wcache = 1;
883
884 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885}
886
887static void ide_cacheflush_p(ide_drive_t *drive)
888{
889 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
890 return;
891
892 if (do_idedisk_flushcache(drive))
893 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
894}
895
Russell King4031bbe2006-01-06 11:41:00 +0000896static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897{
898 struct ide_disk_obj *idkp = drive->driver_data;
899 struct gendisk *g = idkp->disk;
900
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200901 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 del_gendisk(g);
904
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100905 ide_cacheflush_p(drive);
906
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
910static void ide_disk_release(struct kref *kref)
911{
912 struct ide_disk_obj *idkp = to_ide_disk(kref);
913 ide_drive_t *drive = idkp->drive;
914 struct gendisk *g = idkp->disk;
915
916 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 g->private_data = NULL;
918 put_disk(g);
919 kfree(idkp);
920}
921
Russell King4031bbe2006-01-06 11:41:00 +0000922static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Lee Trager0d2157f2007-06-08 15:14:30 +0200924/*
925 * On HPA drives the capacity needs to be
926 * reinitilized on resume otherwise the disk
927 * can not be used and a hard reset is required
928 */
929static void ide_disk_resume(ide_drive_t *drive)
930{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200931 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200932 init_idedisk_capacity(drive);
933}
934
Russell King4031bbe2006-01-06 11:41:00 +0000935static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937#ifdef CONFIG_ALPHA
938 /* On Alpha, halt(8) doesn't actually turn the machine off,
939 it puts you into the sort of firmware monitor. Typically,
940 it's used to boot another kernel image, so it's not much
941 different from reboot(8). Therefore, we don't need to
942 spin down the disk in this case, especially since Alpha
943 firmware doesn't handle disks in standby mode properly.
944 On the other hand, it's reasonably safe to turn the power
945 off when the shutdown process reaches the firmware prompt,
946 as the firmware initialization takes rather long time -
947 at least 10 seconds, which should be sufficient for
948 the disk to expire its write cache. */
949 if (system_state != SYSTEM_POWER_OFF) {
950#else
951 if (system_state == SYSTEM_RESTART) {
952#endif
953 ide_cacheflush_p(drive);
954 return;
955 }
956
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100957 printk(KERN_INFO "Shutdown: %s\n", drive->name);
958
Russell King4031bbe2006-01-06 11:41:00 +0000959 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960}
961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100964 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200965 .name = "ide-disk",
966 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 },
Russell King4031bbe2006-01-06 11:41:00 +0000968 .probe = ide_disk_probe,
969 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200970 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000971 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 .version = IDEDISK_VERSION,
973 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 .do_request = ide_do_rw_disk,
976 .end_request = ide_end_request,
977 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200978#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200980#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981};
982
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100983static int idedisk_set_doorlock(ide_drive_t *drive, int on)
984{
985 ide_task_t task;
986
987 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200988 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100989 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100990
991 return ide_no_data_taskfile(drive, &task);
992}
993
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994static int idedisk_open(struct inode *inode, struct file *filp)
995{
996 struct gendisk *disk = inode->i_bdev->bd_disk;
997 struct ide_disk_obj *idkp;
998 ide_drive_t *drive;
999
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001000 idkp = ide_disk_get(disk);
1001 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 return -ENXIO;
1003
1004 drive = idkp->drive;
1005
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001006 idkp->openers++;
1007
1008 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 check_disk_change(inode->i_bdev);
1010 /*
1011 * Ignore the return code from door_lock,
1012 * since the open() has already succeeded,
1013 * and the door_lock is irrelevant at this point.
1014 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001015 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 drive->doorlocking = 0;
1017 }
1018 return 0;
1019}
1020
1021static int idedisk_release(struct inode *inode, struct file *filp)
1022{
1023 struct gendisk *disk = inode->i_bdev->bd_disk;
1024 struct ide_disk_obj *idkp = ide_disk_g(disk);
1025 ide_drive_t *drive = idkp->drive;
1026
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001027 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001029
1030 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001031 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 drive->doorlocking = 0;
1033 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001034
1035 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037 ide_disk_put(idkp);
1038
1039 return 0;
1040}
1041
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001042static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1043{
1044 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1045 ide_drive_t *drive = idkp->drive;
1046
1047 geo->heads = drive->bios_head;
1048 geo->sectors = drive->bios_sect;
1049 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1050 return 0;
1051}
1052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053static int idedisk_ioctl(struct inode *inode, struct file *file,
1054 unsigned int cmd, unsigned long arg)
1055{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001056 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 struct block_device *bdev = inode->i_bdev;
1058 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001059 ide_drive_t *drive = idkp->drive;
1060 int err, (*setfunc)(ide_drive_t *, int);
1061 u8 *val;
1062
1063 switch (cmd) {
1064 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1065 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1066 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1067 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1068 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1069 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1070 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1071 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1072 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1073 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1074 }
1075
1076 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1077
1078read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001079 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001080 spin_lock_irqsave(&ide_lock, flags);
1081 err = *val;
1082 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001083 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001084 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1085
1086set_val:
1087 if (bdev != bdev->bd_contains)
1088 err = -EINVAL;
1089 else {
1090 if (!capable(CAP_SYS_ADMIN))
1091 err = -EACCES;
1092 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001093 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001094 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001095 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001096 }
1097 }
1098 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099}
1100
1101static int idedisk_media_changed(struct gendisk *disk)
1102{
1103 struct ide_disk_obj *idkp = ide_disk_g(disk);
1104 ide_drive_t *drive = idkp->drive;
1105
1106 /* do not scan partitions twice if this is a removable device */
1107 if (drive->attach) {
1108 drive->attach = 0;
1109 return 0;
1110 }
1111 /* if removable, always assume it was changed */
1112 return drive->removable;
1113}
1114
1115static int idedisk_revalidate_disk(struct gendisk *disk)
1116{
1117 struct ide_disk_obj *idkp = ide_disk_g(disk);
1118 set_capacity(disk, idedisk_capacity(idkp->drive));
1119 return 0;
1120}
1121
1122static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001123 .owner = THIS_MODULE,
1124 .open = idedisk_open,
1125 .release = idedisk_release,
1126 .ioctl = idedisk_ioctl,
1127 .getgeo = idedisk_getgeo,
1128 .media_changed = idedisk_media_changed,
1129 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130};
1131
1132MODULE_DESCRIPTION("ATA DISK Driver");
1133
Russell King4031bbe2006-01-06 11:41:00 +00001134static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
1136 struct ide_disk_obj *idkp;
1137 struct gendisk *g;
1138
1139 /* strstr("foo", "") is non-NULL */
1140 if (!strstr("ide-disk", drive->driver_req))
1141 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001142
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 if (drive->media != ide_disk)
1144 goto failed;
1145
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001146 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 if (!idkp)
1148 goto failed;
1149
Tejun Heo689d6fa2008-08-25 19:56:16 +09001150 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (!g)
1152 goto out_free_idkp;
1153
1154 ide_init_disk(g, drive);
1155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 kref_init(&idkp->kref);
1157
1158 idkp->drive = drive;
1159 idkp->driver = &idedisk_driver;
1160 idkp->disk = g;
1161
1162 g->private_data = &idkp->driver;
1163
1164 drive->driver_data = idkp;
1165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 idedisk_setup(drive);
1167 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1168 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1169 drive->name, drive->head);
1170 drive->attach = 0;
1171 } else
1172 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001173
Tejun Heof615b482008-08-25 19:47:24 +09001174 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001176 g->flags |= GENHD_FL_EXT_DEVT;
1177 if (drive->removable)
1178 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 set_capacity(g, idedisk_capacity(drive));
1180 g->fops = &idedisk_ops;
1181 add_disk(g);
1182 return 0;
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184out_free_idkp:
1185 kfree(idkp);
1186failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001187 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188}
1189
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001190static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001192 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193}
1194
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001195static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001197 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198}
1199
Kay Sievers263756e2005-12-12 18:03:44 +01001200MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201module_init(idedisk_init);
1202module_exit(idedisk_exit);
1203MODULE_LICENSE("GPL");