blob: eeb2c3b22e9791c0793ce57cdafbcf1165e2e2ce [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>
34
35#include <asm/byteorder.h>
36#include <asm/irq.h>
37#include <asm/uaccess.h>
38#include <asm/io.h>
39#include <asm/div64.h>
40
Tejun Heo870d6652008-08-25 19:47:25 +090041#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
Tejun Heo689d6fa2008-08-25 19:56:16 +090042#define IDE_DISK_MINORS (1 << PARTN_BITS)
Tejun Heo870d6652008-08-25 19:47:25 +090043#else
Tejun Heo3e1a7ff2008-08-25 19:56:17 +090044#define IDE_DISK_MINORS 0
Tejun Heo870d6652008-08-25 19:47:25 +090045#endif
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047struct ide_disk_obj {
48 ide_drive_t *drive;
49 ide_driver_t *driver;
50 struct gendisk *disk;
51 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010052 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070053};
54
Arjan van de Vencf8b8972006-03-23 03:00:45 -080055static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
58
59#define ide_disk_g(disk) \
60 container_of((disk)->private_data, struct ide_disk_obj, driver)
61
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020062static void ide_disk_release(struct kref *);
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
65{
66 struct ide_disk_obj *idkp = NULL;
67
Arjan van de Vencf8b8972006-03-23 03:00:45 -080068 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020070 if (idkp) {
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020071 if (ide_device_get(idkp->drive))
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020072 idkp = NULL;
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020073 else
74 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020075 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080076 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 return idkp;
78}
79
Linus Torvalds1da177e2005-04-16 15:20:36 -070080static void ide_disk_put(struct ide_disk_obj *idkp)
81{
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020082 ide_drive_t *drive = idkp->drive;
83
Arjan van de Vencf8b8972006-03-23 03:00:45 -080084 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 kref_put(&idkp->kref, ide_disk_release);
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020086 ide_device_put(drive);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080087 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088}
89
90/*
91 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
92 * value for this drive (from its reported identification information).
93 *
94 * Returns: 1 if lba_capacity looks sensible
95 * 0 otherwise
96 *
97 * It is called only once for each drive.
98 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +020099static int lba_capacity_is_ok(u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100{
101 unsigned long lba_sects, chs_sects, head, tail;
102
Alan Cox6efd9362005-06-27 15:24:22 -0700103 /* No non-LBA info .. so valid! */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200104 if (id[ATA_ID_CYLS] == 0)
Alan Cox6efd9362005-06-27 15:24:22 -0700105 return 1;
106
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200107 lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 /*
110 * The ATA spec tells large drives to return
111 * C/H/S = 16383/16/63 independent of their size.
112 * Some drives can be jumpered to use 15 heads instead of 16.
113 * Some drives can be jumpered to use 4092 cyls instead of 16383.
114 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200115 if ((id[ATA_ID_CYLS] == 16383 ||
116 (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
117 id[ATA_ID_SECTORS] == 63 &&
118 (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200119 (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 return 1;
121
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200122 chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124 /* perform a rough sanity check on lba_sects: within 10% is OK */
125 if ((lba_sects - chs_sects) < chs_sects/10)
126 return 1;
127
128 /* some drives have the word order reversed */
129 head = ((lba_sects >> 16) & 0xffff);
130 tail = (lba_sects & 0xffff);
131 lba_sects = (head | (tail << 16));
132 if ((lba_sects - chs_sects) < chs_sects/10) {
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200133 *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 return 1; /* lba_capacity is (now) good */
135 }
136
137 return 0; /* lba_capacity value may be bad */
138}
139
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100140static const u8 ide_rw_cmds[] = {
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200141 ATA_CMD_READ_MULTI,
142 ATA_CMD_WRITE_MULTI,
143 ATA_CMD_READ_MULTI_EXT,
144 ATA_CMD_WRITE_MULTI_EXT,
145 ATA_CMD_PIO_READ,
146 ATA_CMD_PIO_WRITE,
147 ATA_CMD_PIO_READ_EXT,
148 ATA_CMD_PIO_WRITE_EXT,
149 ATA_CMD_READ,
150 ATA_CMD_WRITE,
151 ATA_CMD_READ_EXT,
152 ATA_CMD_WRITE_EXT,
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100153};
154
155static const u8 ide_data_phases[] = {
156 TASKFILE_MULTI_IN,
157 TASKFILE_MULTI_OUT,
158 TASKFILE_IN,
159 TASKFILE_OUT,
160 TASKFILE_IN_DMA,
161 TASKFILE_OUT_DMA,
162};
163
164static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
165{
166 u8 index, lba48, write;
167
168 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
169 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
170
171 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200172 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100173 else
174 index = drive->mult_count ? 0 : 4;
175
176 task->tf.command = ide_rw_cmds[index + lba48 + write];
177
178 if (dma)
179 index = 8; /* fixup index */
180
181 task->data_phase = ide_data_phases[index / 2 + write];
182}
183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184/*
185 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
186 * using LBA if supported, or CHS otherwise, to address sectors.
187 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200188static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
189 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190{
191 ide_hwif_t *hwif = HWIF(drive);
192 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100193 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100195 ide_task_t task;
196 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100197 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200199 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 if (block + rq->nr_sectors > 1ULL << 28)
201 dma = 0;
202 else
203 lba48 = 0;
204 }
205
206 if (!dma) {
207 ide_init_sg_cmd(drive, rq);
208 ide_map_sg(drive, rq);
209 }
210
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100211 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200212 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 if (drive->select.b.lba) {
215 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800216 pr_debug("%s: LBA=0x%012llx\n", drive->name,
217 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100219 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100220 tf->hob_lbal = (u8)(block >> 24);
221 if (sizeof(block) != 4) {
222 tf->hob_lbam = (u8)((u64)block >> 32);
223 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100225
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100226 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100227 tf->lbal = (u8) block;
228 tf->lbam = (u8)(block >> 8);
229 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100230
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100231 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100233 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100234 tf->lbal = block;
235 tf->lbam = block >>= 8;
236 tf->lbah = block >>= 8;
237 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 }
239 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200240 unsigned int sect, head, cyl, track;
241
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 track = (int)block / drive->sect;
243 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 head = track % drive->head;
245 cyl = track / drive->head;
246
247 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
248
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100249 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100250 tf->lbal = sect;
251 tf->lbam = cyl;
252 tf->lbah = cyl >> 8;
253 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
255
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100256 if (rq_data_dir(rq))
257 task.tf_flags |= IDE_TFLAG_WRITE;
258
259 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100260 if (!dma)
261 hwif->data_phase = task.data_phase;
262 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100263
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100264 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100265
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100266 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100268 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100269 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100270 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100272 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100275 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276}
277
278/*
279 * 268435455 == 137439 MB or 28bit limit
280 * 320173056 == 163929 MB or 48bit addressing
281 * 1073741822 == 549756 MB or 48bit addressing fake drive
282 */
283
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200284static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
285 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
287 ide_hwif_t *hwif = HWIF(drive);
288
289 BUG_ON(drive->blocked);
290
291 if (!blk_fs_request(rq)) {
292 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
293 ide_end_request(drive, 0, 0);
294 return ide_stopped;
295 }
296
Richard Purdie2bfb6462006-03-31 02:31:16 -0800297 ledtrig_ide_activity();
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
300 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800301 (unsigned long long)block, rq->nr_sectors,
302 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304 if (hwif->rw_disk)
305 hwif->rw_disk(drive, rq);
306
307 return __ide_do_rw_disk(drive, rq, block);
308}
309
310/*
311 * Queries for true maximum capacity of the drive.
312 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
313 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100314static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
316 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100317 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100318 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320 /* Create IDE/ATA command request structure */
321 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100322 if (lba48)
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200323 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100324 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200325 tf->command = ATA_CMD_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100326 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100327 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100328 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100329 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100331 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
333 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100334 if ((tf->status & 0x01) == 0)
335 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 return addr;
338}
339
340/*
341 * Sets maximum virtual LBA address of the drive.
342 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
343 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100344static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
346 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100347 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100348 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 addr_req--;
351 /* Create IDE/ATA command request structure */
352 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100353 tf->lbal = (addr_req >> 0) & 0xff;
354 tf->lbam = (addr_req >>= 8) & 0xff;
355 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100356 if (lba48) {
357 tf->hob_lbal = (addr_req >>= 8) & 0xff;
358 tf->hob_lbam = (addr_req >>= 8) & 0xff;
359 tf->hob_lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200360 tf->command = ATA_CMD_SET_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100361 } else {
362 tf->device = (addr_req >>= 8) & 0x0f;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200363 tf->command = ATA_CMD_SET_MAX;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100364 }
365 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100366 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100367 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100368 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100370 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100372 if ((tf->status & 0x01) == 0)
373 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 return addr_set;
376}
377
378static unsigned long long sectors_to_MB(unsigned long long n)
379{
380 n <<= 9; /* make it bytes */
381 do_div(n, 1000000); /* make it MB */
382 return n;
383}
384
385/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 * The same here.
387 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200388static inline int idedisk_supports_lba48(const u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200390 return (id[ATA_ID_COMMAND_SET_2] & 0x0400) &&
391 (id[ATA_ID_CFS_ENABLE_2] & 0x0400) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200392 ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393}
394
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200395/*
396 * Some disks report total number of sectors instead of
397 * maximum sector address. We list them here.
398 */
399static const struct drive_list_entry hpa_list[] = {
400 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200401 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100402 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200403 { NULL, NULL }
404};
405
Arjan van de Ven858119e2006-01-14 13:20:43 -0800406static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{
408 unsigned long long capacity, set_max;
409 int lba48 = idedisk_supports_lba48(drive->id);
410
411 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100412
413 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200415 if (ide_in_drive_list(drive->id, hpa_list)) {
416 /*
417 * Since we are inclusive wrt to firmware revisions do this
418 * extra check and apply the workaround only when needed.
419 */
420 if (set_max == capacity + 1)
421 set_max--;
422 }
423
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 if (set_max <= capacity)
425 return;
426
427 printk(KERN_INFO "%s: Host Protected Area detected.\n"
428 "\tcurrent capacity is %llu sectors (%llu MB)\n"
429 "\tnative capacity is %llu sectors (%llu MB)\n",
430 drive->name,
431 capacity, sectors_to_MB(capacity),
432 set_max, sectors_to_MB(set_max));
433
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100434 set_max = idedisk_set_max_address(drive, set_max, lba48);
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 if (set_max) {
437 drive->capacity64 = set_max;
438 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
439 drive->name);
440 }
441}
442
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200443static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200445 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 /*
447 * If this drive supports the Host Protected Area feature set,
448 * then we may need to change our opinion about the drive's capacity.
449 */
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200450 int hpa = ata_id_hpa_enabled(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
452 if (idedisk_supports_lba48(id)) {
453 /* drive speaks 48-bit LBA */
454 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200455 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 if (hpa)
457 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200458 } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 /* drive speaks 28-bit LBA */
460 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200461 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if (hpa)
463 idedisk_check_hpa(drive);
464 } else {
465 /* drive speaks boring old 28-bit CHS */
466 drive->capacity64 = drive->cyl * drive->head * drive->sect;
467 }
468}
469
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200470static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
Bartlomiej Zolnierkiewicz3c619ff2008-10-10 22:39:22 +0200472 return drive->capacity64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473}
474
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200475#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476static int smart_enable(ide_drive_t *drive)
477{
478 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100479 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200482 tf->feature = ATA_SMART_ENABLE;
483 tf->lbam = ATA_SMART_LBAM_PASS;
484 tf->lbah = ATA_SMART_LBAH_PASS;
485 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100486 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100487 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
489
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200490static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100493 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
495 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100496 tf->feature = sub_cmd;
497 tf->nsect = 0x01;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200498 tf->lbam = ATA_SMART_LBAM_PASS;
499 tf->lbah = ATA_SMART_LBAH_PASS;
500 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100501 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100502 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100504 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505}
506
507static int proc_idedisk_read_cache
508 (char *page, char **start, off_t off, int count, int *eof, void *data)
509{
510 ide_drive_t *drive = (ide_drive_t *) data;
511 char *out = page;
512 int len;
513
514 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200515 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200517 len = sprintf(out, "(none)\n");
518
519 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520}
521
522static int proc_idedisk_read_capacity
523 (char *page, char **start, off_t off, int count, int *eof, void *data)
524{
525 ide_drive_t*drive = (ide_drive_t *)data;
526 int len;
527
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200528 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
529
530 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531}
532
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200533static int proc_idedisk_read_smart(char *page, char **start, off_t off,
534 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 ide_drive_t *drive = (ide_drive_t *)data;
537 int len = 0, i = 0;
538
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200539 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 unsigned short *val = (unsigned short *) page;
541 char *out = ((char *)val) + (SECTOR_WORDS * 4);
542 page = out;
543 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200544 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
545 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 val += 1;
547 } while (i < (SECTOR_WORDS * 2));
548 len = out - page;
549 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200550
551 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552}
553
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200554static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 (char *page, char **start, off_t off, int count, int *eof, void *data)
556{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200557 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200558 ATA_SMART_READ_VALUES);
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200559}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200561static int proc_idedisk_read_st
562 (char *page, char **start, off_t off, int count, int *eof, void *data)
563{
564 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200565 ATA_SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566}
567
568static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200569 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
570 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
571 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
572 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
573 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 { NULL, 0, NULL, NULL }
575};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200576#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Jens Axboe165125e2007-07-24 09:28:11 +0200578static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
580 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100581 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100583 /* FIXME: map struct ide_taskfile on rq->cmd[] */
584 BUG_ON(task == NULL);
585
586 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 if (ide_id_has_flush_cache_ext(drive->id) &&
588 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200589 task->tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200591 task->tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100592 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
593 IDE_TFLAG_DYN;
594 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100596 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200597 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100598 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599}
600
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601/*
602 * This is tightly woven into the driver->do_special can not touch.
603 * DON'T do it again until a total personality rewrite is committed.
604 */
605static int set_multcount(ide_drive_t *drive, int arg)
606{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200607 struct request *rq;
608 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200610 if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200611 return -EINVAL;
612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (drive->special.b.set_multmode)
614 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100615
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200616 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
617 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 drive->mult_req = arg;
620 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200621 error = blk_execute_rq(drive->queue, NULL, rq, 0);
622 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200623
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 return (drive->mult_count == arg) ? 0 : -EIO;
625}
626
627static int set_nowerr(ide_drive_t *drive, int arg)
628{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200629 if (arg < 0 || arg > 1)
630 return -EINVAL;
631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (ide_spin_wait_hwgroup(drive))
633 return -EBUSY;
634 drive->nowerr = arg;
635 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
636 spin_unlock_irq(&ide_lock);
637 return 0;
638}
639
Tejun Heo3e087b52006-01-06 09:57:31 +0100640static void update_ordered(ide_drive_t *drive)
641{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200642 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100643 unsigned ordered = QUEUE_ORDERED_NONE;
644 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100645
646 if (drive->wcache) {
647 unsigned long long capacity;
648 int barrier;
649 /*
650 * We must avoid issuing commands a drive does not
651 * understand or we may crash it. We check flush cache
652 * is supported. We also check we have the LBA48 flush
653 * cache if the drive capacity is too large. By this
654 * time we have trimmed the drive capacity if LBA48 is
655 * not available so we don't need to recheck that.
656 */
657 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200658 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100659 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
660 ide_id_has_flush_cache_ext(id));
661
662 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800663 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100664
665 if (barrier) {
666 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
667 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100668 }
669 } else
670 ordered = QUEUE_ORDERED_DRAIN;
671
672 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100673}
674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675static int write_cache(ide_drive_t *drive, int arg)
676{
677 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100678 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200680 if (arg < 0 || arg > 1)
681 return -EINVAL;
682
Tejun Heo3e087b52006-01-06 09:57:31 +0100683 if (ide_id_has_flush_cache(drive->id)) {
684 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100685 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200686 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
687 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100688 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100689 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100690 if (err == 0)
691 drive->wcache = arg;
692 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Tejun Heo3e087b52006-01-06 09:57:31 +0100694 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Tejun Heo3e087b52006-01-06 09:57:31 +0100696 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697}
698
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200699static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
701 ide_task_t args;
702
703 memset(&args, 0, sizeof(ide_task_t));
704 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200705 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200707 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100708 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100709 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200712static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713{
714 ide_task_t args;
715
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200716 if (arg < 0 || arg > 254)
717 return -EINVAL;
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200720 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100721 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200722 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100723 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100724 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 drive->acoustic = arg;
726 return 0;
727}
728
729/*
730 * drive->addressing:
731 * 0: 28-bit
732 * 1: 48-bit
733 * 2: 48-bit capable doing 28-bit
734 */
735static int set_lba_addressing(ide_drive_t *drive, int arg)
736{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200737 if (arg < 0 || arg > 2)
738 return -EINVAL;
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 drive->addressing = 0;
741
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200742 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return 0;
744
745 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200746 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 drive->addressing = arg;
748 return 0;
749}
750
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200751#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752static void idedisk_add_settings(ide_drive_t *drive)
753{
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200754 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
755 &drive->bios_cyl, NULL);
756 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
757 &drive->bios_head, NULL);
758 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
759 &drive->bios_sect, NULL);
760 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
761 &drive->addressing, set_lba_addressing);
762 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200763 drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1,
764 &drive->mult_count, set_multcount);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200765 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
766 &drive->nowerr, set_nowerr);
767 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
768 &drive->lun, NULL);
769 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
770 &drive->wcache, write_cache);
771 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
772 &drive->acoustic, set_acoustic);
773 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
774 &drive->failures, NULL);
775 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
776 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200778#else
779static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
780#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200782static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200784 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200785 u16 *id = drive->id;
786 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 idedisk_add_settings(drive);
790
791 if (drive->id_read == 0)
792 return;
793
Richard Purdie98109332006-02-03 03:04:55 -0800794 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200796 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200798 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
801
802 (void)set_lba_addressing(drive, 1);
803
804 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 int max_s = 2048;
806
807 if (max_s > hwif->rqsize)
808 max_s = hwif->rqsize;
809
810 blk_queue_max_sectors(drive->queue, max_s);
811 }
812
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200813 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
814 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
816 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200817 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
819 /* limit drive capacity to 137GB if LBA48 cannot be used */
820 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
821 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
822 "%llu sectors (%llu MB)\n",
823 drive->name, (unsigned long long)drive->capacity64,
824 sectors_to_MB(drive->capacity64));
825 drive->capacity64 = 1ULL << 28;
826 }
827
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200828 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200830 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
831 " will be used for accessing sectors "
832 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 } else
834 drive->addressing = 0;
835 }
836
837 /*
838 * if possible, give fdisk access to more of the drive,
839 * by correcting bios_cyls:
840 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200841 capacity = idedisk_capacity(drive);
842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 if (!drive->forced_geom) {
844
845 if (idedisk_supports_lba48(drive->id)) {
846 /* compatibility */
847 drive->bios_sect = 63;
848 drive->bios_head = 255;
849 }
850
851 if (drive->bios_sect && drive->bios_head) {
852 unsigned int cap0 = capacity; /* truncate to 32 bits */
853 unsigned int cylsz, cyl;
854
855 if (cap0 != capacity)
856 drive->bios_cyl = 65535;
857 else {
858 cylsz = drive->bios_sect * drive->bios_head;
859 cyl = cap0 / cylsz;
860 if (cyl > 65535)
861 cyl = 65535;
862 if (cyl > drive->bios_cyl)
863 drive->bios_cyl = cyl;
864 }
865 }
866 }
867 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
868 drive->name, capacity, sectors_to_MB(capacity));
869
870 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200871 if (id[ATA_ID_BUF_SIZE])
872 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100874 printk(KERN_CONT ", CHS=%d/%d/%d\n",
875 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200878 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 drive->wcache = 1;
880
881 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882}
883
884static void ide_cacheflush_p(ide_drive_t *drive)
885{
886 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
887 return;
888
889 if (do_idedisk_flushcache(drive))
890 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
891}
892
Russell King4031bbe2006-01-06 11:41:00 +0000893static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 struct ide_disk_obj *idkp = drive->driver_data;
896 struct gendisk *g = idkp->disk;
897
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200898 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 del_gendisk(g);
901
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100902 ide_cacheflush_p(drive);
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905}
906
907static void ide_disk_release(struct kref *kref)
908{
909 struct ide_disk_obj *idkp = to_ide_disk(kref);
910 ide_drive_t *drive = idkp->drive;
911 struct gendisk *g = idkp->disk;
912
913 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 g->private_data = NULL;
915 put_disk(g);
916 kfree(idkp);
917}
918
Russell King4031bbe2006-01-06 11:41:00 +0000919static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Lee Trager0d2157f2007-06-08 15:14:30 +0200921/*
922 * On HPA drives the capacity needs to be
923 * reinitilized on resume otherwise the disk
924 * can not be used and a hard reset is required
925 */
926static void ide_disk_resume(ide_drive_t *drive)
927{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200928 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200929 init_idedisk_capacity(drive);
930}
931
Russell King4031bbe2006-01-06 11:41:00 +0000932static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934#ifdef CONFIG_ALPHA
935 /* On Alpha, halt(8) doesn't actually turn the machine off,
936 it puts you into the sort of firmware monitor. Typically,
937 it's used to boot another kernel image, so it's not much
938 different from reboot(8). Therefore, we don't need to
939 spin down the disk in this case, especially since Alpha
940 firmware doesn't handle disks in standby mode properly.
941 On the other hand, it's reasonably safe to turn the power
942 off when the shutdown process reaches the firmware prompt,
943 as the firmware initialization takes rather long time -
944 at least 10 seconds, which should be sufficient for
945 the disk to expire its write cache. */
946 if (system_state != SYSTEM_POWER_OFF) {
947#else
948 if (system_state == SYSTEM_RESTART) {
949#endif
950 ide_cacheflush_p(drive);
951 return;
952 }
953
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100954 printk(KERN_INFO "Shutdown: %s\n", drive->name);
955
Russell King4031bbe2006-01-06 11:41:00 +0000956 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957}
958
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100961 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200962 .name = "ide-disk",
963 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 },
Russell King4031bbe2006-01-06 11:41:00 +0000965 .probe = ide_disk_probe,
966 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200967 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000968 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 .version = IDEDISK_VERSION,
970 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 .do_request = ide_do_rw_disk,
973 .end_request = ide_end_request,
974 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200975#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200977#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978};
979
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100980static int idedisk_set_doorlock(ide_drive_t *drive, int on)
981{
982 ide_task_t task;
983
984 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200985 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100986 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100987
988 return ide_no_data_taskfile(drive, &task);
989}
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991static int idedisk_open(struct inode *inode, struct file *filp)
992{
993 struct gendisk *disk = inode->i_bdev->bd_disk;
994 struct ide_disk_obj *idkp;
995 ide_drive_t *drive;
996
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200997 idkp = ide_disk_get(disk);
998 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return -ENXIO;
1000
1001 drive = idkp->drive;
1002
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001003 idkp->openers++;
1004
1005 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 check_disk_change(inode->i_bdev);
1007 /*
1008 * Ignore the return code from door_lock,
1009 * since the open() has already succeeded,
1010 * and the door_lock is irrelevant at this point.
1011 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001012 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 drive->doorlocking = 0;
1014 }
1015 return 0;
1016}
1017
1018static int idedisk_release(struct inode *inode, struct file *filp)
1019{
1020 struct gendisk *disk = inode->i_bdev->bd_disk;
1021 struct ide_disk_obj *idkp = ide_disk_g(disk);
1022 ide_drive_t *drive = idkp->drive;
1023
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001024 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001026
1027 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001028 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 drive->doorlocking = 0;
1030 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001031
1032 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 ide_disk_put(idkp);
1035
1036 return 0;
1037}
1038
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001039static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1040{
1041 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1042 ide_drive_t *drive = idkp->drive;
1043
1044 geo->heads = drive->bios_head;
1045 geo->sectors = drive->bios_sect;
1046 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1047 return 0;
1048}
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050static int idedisk_ioctl(struct inode *inode, struct file *file,
1051 unsigned int cmd, unsigned long arg)
1052{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001053 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 struct block_device *bdev = inode->i_bdev;
1055 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001056 ide_drive_t *drive = idkp->drive;
1057 int err, (*setfunc)(ide_drive_t *, int);
1058 u8 *val;
1059
1060 switch (cmd) {
1061 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1062 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1063 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1064 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1065 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1066 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1067 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1068 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1069 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1070 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1071 }
1072
1073 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1074
1075read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001076 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001077 spin_lock_irqsave(&ide_lock, flags);
1078 err = *val;
1079 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001080 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001081 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1082
1083set_val:
1084 if (bdev != bdev->bd_contains)
1085 err = -EINVAL;
1086 else {
1087 if (!capable(CAP_SYS_ADMIN))
1088 err = -EACCES;
1089 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001090 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001091 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001092 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001093 }
1094 }
1095 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096}
1097
1098static int idedisk_media_changed(struct gendisk *disk)
1099{
1100 struct ide_disk_obj *idkp = ide_disk_g(disk);
1101 ide_drive_t *drive = idkp->drive;
1102
1103 /* do not scan partitions twice if this is a removable device */
1104 if (drive->attach) {
1105 drive->attach = 0;
1106 return 0;
1107 }
1108 /* if removable, always assume it was changed */
1109 return drive->removable;
1110}
1111
1112static int idedisk_revalidate_disk(struct gendisk *disk)
1113{
1114 struct ide_disk_obj *idkp = ide_disk_g(disk);
1115 set_capacity(disk, idedisk_capacity(idkp->drive));
1116 return 0;
1117}
1118
1119static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001120 .owner = THIS_MODULE,
1121 .open = idedisk_open,
1122 .release = idedisk_release,
1123 .ioctl = idedisk_ioctl,
1124 .getgeo = idedisk_getgeo,
1125 .media_changed = idedisk_media_changed,
1126 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127};
1128
1129MODULE_DESCRIPTION("ATA DISK Driver");
1130
Russell King4031bbe2006-01-06 11:41:00 +00001131static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 struct ide_disk_obj *idkp;
1134 struct gendisk *g;
1135
1136 /* strstr("foo", "") is non-NULL */
1137 if (!strstr("ide-disk", drive->driver_req))
1138 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (drive->media != ide_disk)
1141 goto failed;
1142
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001143 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (!idkp)
1145 goto failed;
1146
Tejun Heo689d6fa2008-08-25 19:56:16 +09001147 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 if (!g)
1149 goto out_free_idkp;
1150
1151 ide_init_disk(g, drive);
1152
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001153 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 kref_init(&idkp->kref);
1156
1157 idkp->drive = drive;
1158 idkp->driver = &idedisk_driver;
1159 idkp->disk = g;
1160
1161 g->private_data = &idkp->driver;
1162
1163 drive->driver_data = idkp;
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 idedisk_setup(drive);
1166 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1167 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1168 drive->name, drive->head);
1169 drive->attach = 0;
1170 } else
1171 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001172
Tejun Heof615b482008-08-25 19:47:24 +09001173 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001175 g->flags |= GENHD_FL_EXT_DEVT;
1176 if (drive->removable)
1177 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 set_capacity(g, idedisk_capacity(drive));
1179 g->fops = &idedisk_ops;
1180 add_disk(g);
1181 return 0;
1182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183out_free_idkp:
1184 kfree(idkp);
1185failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001186 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187}
1188
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001189static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001191 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192}
1193
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001194static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001196 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
Kay Sievers263756e2005-12-12 18:03:44 +01001199MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200module_init(idedisk_init);
1201module_exit(idedisk_exit);
1202MODULE_LICENSE("GPL");