blob: 83da9a98dabc5a2259f27fef7cdaa6297febe6a2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Bartlomiej Zolnierkiewicz59bca8c2008-02-01 23:09:33 +01002 * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
3 * Copyright (C) 1998-2002 Linux ATA Development
4 * Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2003 Red Hat <alan@redhat.com>
6 * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
9/*
10 * Mostly written by Mark Lord <mlord@pobox.com>
11 * and Gadi Oxman <gadio@netvision.net.il>
12 * and Andre Hedrick <andre@linux-ide.org>
13 *
14 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 */
16
17#define IDEDISK_VERSION "1.18"
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/mm.h>
25#include <linux/interrupt.h>
26#include <linux/major.h>
27#include <linux/errno.h>
28#include <linux/genhd.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080031#include <linux/mutex.h>
Richard Purdie2bfb6462006-03-31 02:31:16 -080032#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#define _IDE_DISK
35
36#include <linux/ide.h>
37
38#include <asm/byteorder.h>
39#include <asm/irq.h>
40#include <asm/uaccess.h>
41#include <asm/io.h>
42#include <asm/div64.h>
43
Tejun Heo870d6652008-08-25 19:47:25 +090044#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
Tejun Heo689d6fa2008-08-25 19:56:16 +090045#define IDE_DISK_MINORS (1 << PARTN_BITS)
Tejun Heo870d6652008-08-25 19:47:25 +090046#else
Tejun Heo3e1a7ff2008-08-25 19:56:17 +090047#define IDE_DISK_MINORS 0
Tejun Heo870d6652008-08-25 19:47:25 +090048#endif
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050struct ide_disk_obj {
51 ide_drive_t *drive;
52 ide_driver_t *driver;
53 struct gendisk *disk;
54 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010055 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056};
57
Arjan van de Vencf8b8972006-03-23 03:00:45 -080058static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
61
62#define ide_disk_g(disk) \
63 container_of((disk)->private_data, struct ide_disk_obj, driver)
64
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020065static void ide_disk_release(struct kref *);
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
68{
69 struct ide_disk_obj *idkp = NULL;
70
Arjan van de Vencf8b8972006-03-23 03:00:45 -080071 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020073 if (idkp) {
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020074 if (ide_device_get(idkp->drive))
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020075 idkp = NULL;
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020076 else
77 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020078 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080079 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return idkp;
81}
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083static void ide_disk_put(struct ide_disk_obj *idkp)
84{
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020085 ide_drive_t *drive = idkp->drive;
86
Arjan van de Vencf8b8972006-03-23 03:00:45 -080087 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 kref_put(&idkp->kref, ide_disk_release);
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020089 ide_device_put(drive);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080090 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
92
93/*
94 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
95 * value for this drive (from its reported identification information).
96 *
97 * Returns: 1 if lba_capacity looks sensible
98 * 0 otherwise
99 *
100 * It is called only once for each drive.
101 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200102static int lba_capacity_is_ok(u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103{
104 unsigned long lba_sects, chs_sects, head, tail;
105
Alan Cox6efd9362005-06-27 15:24:22 -0700106 /* No non-LBA info .. so valid! */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200107 if (id[ATA_ID_CYLS] == 0)
Alan Cox6efd9362005-06-27 15:24:22 -0700108 return 1;
109
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200110 lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 /*
113 * The ATA spec tells large drives to return
114 * C/H/S = 16383/16/63 independent of their size.
115 * Some drives can be jumpered to use 15 heads instead of 16.
116 * Some drives can be jumpered to use 4092 cyls instead of 16383.
117 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200118 if ((id[ATA_ID_CYLS] == 16383 ||
119 (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
120 id[ATA_ID_SECTORS] == 63 &&
121 (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200122 (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return 1;
124
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200125 chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 /* perform a rough sanity check on lba_sects: within 10% is OK */
128 if ((lba_sects - chs_sects) < chs_sects/10)
129 return 1;
130
131 /* some drives have the word order reversed */
132 head = ((lba_sects >> 16) & 0xffff);
133 tail = (lba_sects & 0xffff);
134 lba_sects = (head | (tail << 16));
135 if ((lba_sects - chs_sects) < chs_sects/10) {
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200136 *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 return 1; /* lba_capacity is (now) good */
138 }
139
140 return 0; /* lba_capacity value may be bad */
141}
142
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100143static const u8 ide_rw_cmds[] = {
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200144 ATA_CMD_READ_MULTI,
145 ATA_CMD_WRITE_MULTI,
146 ATA_CMD_READ_MULTI_EXT,
147 ATA_CMD_WRITE_MULTI_EXT,
148 ATA_CMD_PIO_READ,
149 ATA_CMD_PIO_WRITE,
150 ATA_CMD_PIO_READ_EXT,
151 ATA_CMD_PIO_WRITE_EXT,
152 ATA_CMD_READ,
153 ATA_CMD_WRITE,
154 ATA_CMD_READ_EXT,
155 ATA_CMD_WRITE_EXT,
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100156};
157
158static const u8 ide_data_phases[] = {
159 TASKFILE_MULTI_IN,
160 TASKFILE_MULTI_OUT,
161 TASKFILE_IN,
162 TASKFILE_OUT,
163 TASKFILE_IN_DMA,
164 TASKFILE_OUT_DMA,
165};
166
167static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
168{
169 u8 index, lba48, write;
170
171 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
172 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
173
174 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200175 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100176 else
177 index = drive->mult_count ? 0 : 4;
178
179 task->tf.command = ide_rw_cmds[index + lba48 + write];
180
181 if (dma)
182 index = 8; /* fixup index */
183
184 task->data_phase = ide_data_phases[index / 2 + write];
185}
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187/*
188 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
189 * using LBA if supported, or CHS otherwise, to address sectors.
190 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200191static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
192 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193{
194 ide_hwif_t *hwif = HWIF(drive);
195 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100196 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100198 ide_task_t task;
199 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100200 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200202 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 if (block + rq->nr_sectors > 1ULL << 28)
204 dma = 0;
205 else
206 lba48 = 0;
207 }
208
209 if (!dma) {
210 ide_init_sg_cmd(drive, rq);
211 ide_map_sg(drive, rq);
212 }
213
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100214 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200215 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100216
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 if (drive->select.b.lba) {
218 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800219 pr_debug("%s: LBA=0x%012llx\n", drive->name,
220 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100222 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100223 tf->hob_lbal = (u8)(block >> 24);
224 if (sizeof(block) != 4) {
225 tf->hob_lbam = (u8)((u64)block >> 32);
226 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100228
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100229 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100230 tf->lbal = (u8) block;
231 tf->lbam = (u8)(block >> 8);
232 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100233
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100234 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100236 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100237 tf->lbal = block;
238 tf->lbam = block >>= 8;
239 tf->lbah = block >>= 8;
240 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 }
242 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200243 unsigned int sect, head, cyl, track;
244
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 track = (int)block / drive->sect;
246 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 head = track % drive->head;
248 cyl = track / drive->head;
249
250 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
251
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100252 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100253 tf->lbal = sect;
254 tf->lbam = cyl;
255 tf->lbah = cyl >> 8;
256 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 }
258
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100259 if (rq_data_dir(rq))
260 task.tf_flags |= IDE_TFLAG_WRITE;
261
262 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100263 if (!dma)
264 hwif->data_phase = task.data_phase;
265 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100266
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100267 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100268
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100269 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100271 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100272 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100273 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100275 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100278 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279}
280
281/*
282 * 268435455 == 137439 MB or 28bit limit
283 * 320173056 == 163929 MB or 48bit addressing
284 * 1073741822 == 549756 MB or 48bit addressing fake drive
285 */
286
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200287static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
288 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289{
290 ide_hwif_t *hwif = HWIF(drive);
291
292 BUG_ON(drive->blocked);
293
294 if (!blk_fs_request(rq)) {
295 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
296 ide_end_request(drive, 0, 0);
297 return ide_stopped;
298 }
299
Richard Purdie2bfb6462006-03-31 02:31:16 -0800300 ledtrig_ide_activity();
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
303 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800304 (unsigned long long)block, rq->nr_sectors,
305 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
307 if (hwif->rw_disk)
308 hwif->rw_disk(drive, rq);
309
310 return __ide_do_rw_disk(drive, rq, block);
311}
312
313/*
314 * Queries for true maximum capacity of the drive.
315 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
316 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100317static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100320 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100321 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 /* Create IDE/ATA command request structure */
324 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100325 if (lba48)
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200326 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100327 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200328 tf->command = ATA_CMD_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100329 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100330 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100331 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100332 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100334 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100337 if ((tf->status & 0x01) == 0)
338 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 return addr;
341}
342
343/*
344 * Sets maximum virtual LBA address of the drive.
345 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
346 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100347static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
349 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100350 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100351 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 addr_req--;
354 /* Create IDE/ATA command request structure */
355 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100356 tf->lbal = (addr_req >> 0) & 0xff;
357 tf->lbam = (addr_req >>= 8) & 0xff;
358 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100359 if (lba48) {
360 tf->hob_lbal = (addr_req >>= 8) & 0xff;
361 tf->hob_lbam = (addr_req >>= 8) & 0xff;
362 tf->hob_lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200363 tf->command = ATA_CMD_SET_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100364 } else {
365 tf->device = (addr_req >>= 8) & 0x0f;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200366 tf->command = ATA_CMD_SET_MAX;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100367 }
368 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100369 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100370 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100371 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100373 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100375 if ((tf->status & 0x01) == 0)
376 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 return addr_set;
379}
380
381static unsigned long long sectors_to_MB(unsigned long long n)
382{
383 n <<= 9; /* make it bytes */
384 do_div(n, 1000000); /* make it MB */
385 return n;
386}
387
388/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 * The same here.
390 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200391static inline int idedisk_supports_lba48(const u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200393 return (id[ATA_ID_COMMAND_SET_2] & 0x0400) &&
394 (id[ATA_ID_CFS_ENABLE_2] & 0x0400) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200395 ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396}
397
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200398/*
399 * Some disks report total number of sectors instead of
400 * maximum sector address. We list them here.
401 */
402static const struct drive_list_entry hpa_list[] = {
403 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200404 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100405 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200406 { NULL, NULL }
407};
408
Arjan van de Ven858119e2006-01-14 13:20:43 -0800409static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
411 unsigned long long capacity, set_max;
412 int lba48 = idedisk_supports_lba48(drive->id);
413
414 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100415
416 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200418 if (ide_in_drive_list(drive->id, hpa_list)) {
419 /*
420 * Since we are inclusive wrt to firmware revisions do this
421 * extra check and apply the workaround only when needed.
422 */
423 if (set_max == capacity + 1)
424 set_max--;
425 }
426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 if (set_max <= capacity)
428 return;
429
430 printk(KERN_INFO "%s: Host Protected Area detected.\n"
431 "\tcurrent capacity is %llu sectors (%llu MB)\n"
432 "\tnative capacity is %llu sectors (%llu MB)\n",
433 drive->name,
434 capacity, sectors_to_MB(capacity),
435 set_max, sectors_to_MB(set_max));
436
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100437 set_max = idedisk_set_max_address(drive, set_max, lba48);
438
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 if (set_max) {
440 drive->capacity64 = set_max;
441 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
442 drive->name);
443 }
444}
445
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200446static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200448 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 /*
450 * If this drive supports the Host Protected Area feature set,
451 * then we may need to change our opinion about the drive's capacity.
452 */
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200453 int hpa = ata_id_hpa_enabled(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455 if (idedisk_supports_lba48(id)) {
456 /* drive speaks 48-bit LBA */
457 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200458 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 if (hpa)
460 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200461 } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 /* drive speaks 28-bit LBA */
463 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200464 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 if (hpa)
466 idedisk_check_hpa(drive);
467 } else {
468 /* drive speaks boring old 28-bit CHS */
469 drive->capacity64 = drive->cyl * drive->head * drive->sect;
470 }
471}
472
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200473static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 return drive->capacity64 - drive->sect0;
476}
477
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200478#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479static int smart_enable(ide_drive_t *drive)
480{
481 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100482 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200485 tf->feature = ATA_SMART_ENABLE;
486 tf->lbam = ATA_SMART_LBAM_PASS;
487 tf->lbah = ATA_SMART_LBAH_PASS;
488 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100489 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100490 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491}
492
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200493static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
495 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100496 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100499 tf->feature = sub_cmd;
500 tf->nsect = 0x01;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200501 tf->lbam = ATA_SMART_LBAM_PASS;
502 tf->lbah = ATA_SMART_LBAH_PASS;
503 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100504 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100505 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100507 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508}
509
510static int proc_idedisk_read_cache
511 (char *page, char **start, off_t off, int count, int *eof, void *data)
512{
513 ide_drive_t *drive = (ide_drive_t *) data;
514 char *out = page;
515 int len;
516
517 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200518 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200520 len = sprintf(out, "(none)\n");
521
522 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523}
524
525static int proc_idedisk_read_capacity
526 (char *page, char **start, off_t off, int count, int *eof, void *data)
527{
528 ide_drive_t*drive = (ide_drive_t *)data;
529 int len;
530
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200531 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
532
533 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}
535
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200536static int proc_idedisk_read_smart(char *page, char **start, off_t off,
537 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538{
539 ide_drive_t *drive = (ide_drive_t *)data;
540 int len = 0, i = 0;
541
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200542 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 unsigned short *val = (unsigned short *) page;
544 char *out = ((char *)val) + (SECTOR_WORDS * 4);
545 page = out;
546 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200547 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
548 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 val += 1;
550 } while (i < (SECTOR_WORDS * 2));
551 len = out - page;
552 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200553
554 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200557static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 (char *page, char **start, off_t off, int count, int *eof, void *data)
559{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200560 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200561 ATA_SMART_READ_VALUES);
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200562}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200564static int proc_idedisk_read_st
565 (char *page, char **start, off_t off, int count, int *eof, void *data)
566{
567 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200568 ATA_SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569}
570
571static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200572 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
573 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
574 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
575 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
576 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 { NULL, 0, NULL, NULL }
578};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200579#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Jens Axboe165125e2007-07-24 09:28:11 +0200581static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
583 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100584 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100586 /* FIXME: map struct ide_taskfile on rq->cmd[] */
587 BUG_ON(task == NULL);
588
589 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 if (ide_id_has_flush_cache_ext(drive->id) &&
591 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200592 task->tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200594 task->tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100595 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
596 IDE_TFLAG_DYN;
597 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100599 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200600 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100601 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602}
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
630static int set_nowerr(ide_drive_t *drive, int arg)
631{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200632 if (arg < 0 || arg > 1)
633 return -EINVAL;
634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 if (ide_spin_wait_hwgroup(drive))
636 return -EBUSY;
637 drive->nowerr = arg;
638 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
639 spin_unlock_irq(&ide_lock);
640 return 0;
641}
642
Tejun Heo3e087b52006-01-06 09:57:31 +0100643static void update_ordered(ide_drive_t *drive)
644{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200645 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100646 unsigned ordered = QUEUE_ORDERED_NONE;
647 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100648
649 if (drive->wcache) {
650 unsigned long long capacity;
651 int barrier;
652 /*
653 * We must avoid issuing commands a drive does not
654 * understand or we may crash it. We check flush cache
655 * is supported. We also check we have the LBA48 flush
656 * cache if the drive capacity is too large. By this
657 * time we have trimmed the drive capacity if LBA48 is
658 * not available so we don't need to recheck that.
659 */
660 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200661 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100662 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
663 ide_id_has_flush_cache_ext(id));
664
665 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800666 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100667
668 if (barrier) {
669 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
670 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100671 }
672 } else
673 ordered = QUEUE_ORDERED_DRAIN;
674
675 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100676}
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678static int write_cache(ide_drive_t *drive, int arg)
679{
680 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100681 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200683 if (arg < 0 || arg > 1)
684 return -EINVAL;
685
Tejun Heo3e087b52006-01-06 09:57:31 +0100686 if (ide_id_has_flush_cache(drive->id)) {
687 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100688 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200689 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
690 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100691 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100692 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100693 if (err == 0)
694 drive->wcache = arg;
695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Tejun Heo3e087b52006-01-06 09:57:31 +0100697 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Tejun Heo3e087b52006-01-06 09:57:31 +0100699 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200702static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 ide_task_t args;
705
706 memset(&args, 0, sizeof(ide_task_t));
707 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200708 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200710 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100711 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100712 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200715static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716{
717 ide_task_t args;
718
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200719 if (arg < 0 || arg > 254)
720 return -EINVAL;
721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200723 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100724 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200725 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100726 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100727 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 drive->acoustic = arg;
729 return 0;
730}
731
732/*
733 * drive->addressing:
734 * 0: 28-bit
735 * 1: 48-bit
736 * 2: 48-bit capable doing 28-bit
737 */
738static int set_lba_addressing(ide_drive_t *drive, int arg)
739{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200740 if (arg < 0 || arg > 2)
741 return -EINVAL;
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 drive->addressing = 0;
744
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200745 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 return 0;
747
748 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200749 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 drive->addressing = arg;
751 return 0;
752}
753
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200754#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755static void idedisk_add_settings(ide_drive_t *drive)
756{
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200757 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
758 &drive->bios_cyl, NULL);
759 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
760 &drive->bios_head, NULL);
761 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
762 &drive->bios_sect, NULL);
763 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
764 &drive->addressing, set_lba_addressing);
765 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200766 drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1,
767 &drive->mult_count, set_multcount);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200768 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
769 &drive->nowerr, set_nowerr);
770 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
771 &drive->lun, NULL);
772 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
773 &drive->wcache, write_cache);
774 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
775 &drive->acoustic, set_acoustic);
776 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
777 &drive->failures, NULL);
778 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
779 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200781#else
782static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
783#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200785static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200787 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200788 u16 *id = drive->id;
789 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 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;
1142 if (!drive->present)
1143 goto failed;
1144 if (drive->media != ide_disk)
1145 goto failed;
1146
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001147 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 if (!idkp)
1149 goto failed;
1150
Tejun Heo689d6fa2008-08-25 19:56:16 +09001151 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (!g)
1153 goto out_free_idkp;
1154
1155 ide_init_disk(g, drive);
1156
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001157 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 kref_init(&idkp->kref);
1160
1161 idkp->drive = drive;
1162 idkp->driver = &idedisk_driver;
1163 idkp->disk = g;
1164
1165 g->private_data = &idkp->driver;
1166
1167 drive->driver_data = idkp;
1168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 idedisk_setup(drive);
1170 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1171 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1172 drive->name, drive->head);
1173 drive->attach = 0;
1174 } else
1175 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001176
Tejun Heof615b482008-08-25 19:47:24 +09001177 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001179 g->flags |= GENHD_FL_EXT_DEVT;
1180 if (drive->removable)
1181 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 set_capacity(g, idedisk_capacity(drive));
1183 g->fops = &idedisk_ops;
1184 add_disk(g);
1185 return 0;
1186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187out_free_idkp:
1188 kfree(idkp);
1189failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001190 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191}
1192
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001193static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001195 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196}
1197
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001198static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001200 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
Kay Sievers263756e2005-12-12 18:03:44 +01001203MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204module_init(idedisk_init);
1205module_exit(idedisk_exit);
1206MODULE_LICENSE("GPL");