blob: f1669bca3cab1669178cffedfc5d96b073c74e8f [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{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200104 struct hd_driveid *driveid = (struct hd_driveid *)id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 unsigned long lba_sects, chs_sects, head, tail;
106
Alan Cox6efd9362005-06-27 15:24:22 -0700107 /* No non-LBA info .. so valid! */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200108 if (id[ATA_ID_CYLS] == 0)
Alan Cox6efd9362005-06-27 15:24:22 -0700109 return 1;
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 /*
112 * The ATA spec tells large drives to return
113 * C/H/S = 16383/16/63 independent of their size.
114 * Some drives can be jumpered to use 15 heads instead of 16.
115 * Some drives can be jumpered to use 4092 cyls instead of 16383.
116 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200117 if ((id[ATA_ID_CYLS] == 16383 ||
118 (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
119 id[ATA_ID_SECTORS] == 63 &&
120 (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
121 (driveid->lba_capacity >= 16383 * 63 * id[ATA_ID_HEADS]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 return 1;
123
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200124 lba_sects = driveid->lba_capacity;
125 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 Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200136 driveid->lba_capacity = 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[] = {
144 WIN_MULTREAD,
145 WIN_MULTWRITE,
146 WIN_MULTREAD_EXT,
147 WIN_MULTWRITE_EXT,
148 WIN_READ,
149 WIN_WRITE,
150 WIN_READ_EXT,
151 WIN_WRITE_EXT,
152 WIN_READDMA,
153 WIN_WRITEDMA,
154 WIN_READDMA_EXT,
155 WIN_WRITEDMA_EXT,
156};
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)
326 tf->command = WIN_READ_NATIVE_MAX_EXT;
327 else
328 tf->command = WIN_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;
363 tf->command = WIN_SET_MAX_EXT;
364 } else {
365 tf->device = (addr_req >>= 8) & 0x0f;
366 tf->command = WIN_SET_MAX;
367 }
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/*
389 * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
390 * so on non-buggy drives we need test only one.
391 * However, we should also check whether these fields are valid.
392 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200393static inline int idedisk_supports_hpa(const u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200395 return (id[ATA_ID_COMMAND_SET_1] & 0x0400) &&
396 (id[ATA_ID_CFS_ENABLE_1] & 0x0400);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397}
398
399/*
400 * The same here.
401 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200402static inline int idedisk_supports_lba48(const u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200404 return (id[ATA_ID_COMMAND_SET_2] & 0x0400) &&
405 (id[ATA_ID_CFS_ENABLE_2] & 0x0400) &&
406 ((struct hd_driveid *)id)->lba_capacity_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200409/*
410 * Some disks report total number of sectors instead of
411 * maximum sector address. We list them here.
412 */
413static const struct drive_list_entry hpa_list[] = {
414 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200415 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100416 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200417 { NULL, NULL }
418};
419
Arjan van de Ven858119e2006-01-14 13:20:43 -0800420static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
422 unsigned long long capacity, set_max;
423 int lba48 = idedisk_supports_lba48(drive->id);
424
425 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100426
427 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200429 if (ide_in_drive_list(drive->id, hpa_list)) {
430 /*
431 * Since we are inclusive wrt to firmware revisions do this
432 * extra check and apply the workaround only when needed.
433 */
434 if (set_max == capacity + 1)
435 set_max--;
436 }
437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 if (set_max <= capacity)
439 return;
440
441 printk(KERN_INFO "%s: Host Protected Area detected.\n"
442 "\tcurrent capacity is %llu sectors (%llu MB)\n"
443 "\tnative capacity is %llu sectors (%llu MB)\n",
444 drive->name,
445 capacity, sectors_to_MB(capacity),
446 set_max, sectors_to_MB(set_max));
447
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100448 set_max = idedisk_set_max_address(drive, set_max, lba48);
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 if (set_max) {
451 drive->capacity64 = set_max;
452 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
453 drive->name);
454 }
455}
456
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200457static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200459 struct hd_driveid *driveid = drive->driveid;
460 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 /*
462 * If this drive supports the Host Protected Area feature set,
463 * then we may need to change our opinion about the drive's capacity.
464 */
465 int hpa = idedisk_supports_hpa(id);
466
467 if (idedisk_supports_lba48(id)) {
468 /* drive speaks 48-bit LBA */
469 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200470 drive->capacity64 = driveid->lba_capacity_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 if (hpa)
472 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200473 } else if ((driveid->capability & 2) && lba_capacity_is_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 /* drive speaks 28-bit LBA */
475 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200476 drive->capacity64 = driveid->lba_capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 if (hpa)
478 idedisk_check_hpa(drive);
479 } else {
480 /* drive speaks boring old 28-bit CHS */
481 drive->capacity64 = drive->cyl * drive->head * drive->sect;
482 }
483}
484
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200485static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486{
487 return drive->capacity64 - drive->sect0;
488}
489
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200490#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491static int smart_enable(ide_drive_t *drive)
492{
493 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100494 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100497 tf->feature = SMART_ENABLE;
498 tf->lbam = SMART_LCYL_PASS;
499 tf->lbah = SMART_HCYL_PASS;
500 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100501 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100502 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503}
504
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200505static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100508 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100511 tf->feature = sub_cmd;
512 tf->nsect = 0x01;
513 tf->lbam = SMART_LCYL_PASS;
514 tf->lbah = SMART_HCYL_PASS;
515 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100516 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100517 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100519 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520}
521
522static int proc_idedisk_read_cache
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 char *out = page;
527 int len;
528
529 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200530 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200532 len = sprintf(out, "(none)\n");
533
534 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535}
536
537static int proc_idedisk_read_capacity
538 (char *page, char **start, off_t off, int count, int *eof, void *data)
539{
540 ide_drive_t*drive = (ide_drive_t *)data;
541 int len;
542
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200543 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
544
545 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546}
547
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200548static int proc_idedisk_read_smart(char *page, char **start, off_t off,
549 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 ide_drive_t *drive = (ide_drive_t *)data;
552 int len = 0, i = 0;
553
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200554 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 unsigned short *val = (unsigned short *) page;
556 char *out = ((char *)val) + (SECTOR_WORDS * 4);
557 page = out;
558 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200559 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
560 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 val += 1;
562 } while (i < (SECTOR_WORDS * 2));
563 len = out - page;
564 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200565
566 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567}
568
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200569static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 (char *page, char **start, off_t off, int count, int *eof, void *data)
571{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200572 return proc_idedisk_read_smart(page, start, off, count, eof, data,
573 SMART_READ_VALUES);
574}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200576static int proc_idedisk_read_st
577 (char *page, char **start, off_t off, int count, int *eof, void *data)
578{
579 return proc_idedisk_read_smart(page, start, off, count, eof, data,
580 SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581}
582
583static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200584 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
585 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
586 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
587 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
588 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 { NULL, 0, NULL, NULL }
590};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200591#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Jens Axboe165125e2007-07-24 09:28:11 +0200593static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594{
595 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100596 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100598 /* FIXME: map struct ide_taskfile on rq->cmd[] */
599 BUG_ON(task == NULL);
600
601 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (ide_id_has_flush_cache_ext(drive->id) &&
603 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100604 task->tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 else
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100606 task->tf.command = WIN_FLUSH_CACHE;
607 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
608 IDE_TFLAG_DYN;
609 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100611 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200612 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100613 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616/*
617 * This is tightly woven into the driver->do_special can not touch.
618 * DON'T do it again until a total personality rewrite is committed.
619 */
620static int set_multcount(ide_drive_t *drive, int arg)
621{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200622 struct request *rq;
623 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200625 if (arg < 0 || arg > drive->driveid->max_multsect)
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200626 return -EINVAL;
627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 if (drive->special.b.set_multmode)
629 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100630
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200631 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
632 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 drive->mult_req = arg;
635 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200636 error = blk_execute_rq(drive->queue, NULL, rq, 0);
637 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return (drive->mult_count == arg) ? 0 : -EIO;
640}
641
642static int set_nowerr(ide_drive_t *drive, int arg)
643{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200644 if (arg < 0 || arg > 1)
645 return -EINVAL;
646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 if (ide_spin_wait_hwgroup(drive))
648 return -EBUSY;
649 drive->nowerr = arg;
650 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
651 spin_unlock_irq(&ide_lock);
652 return 0;
653}
654
Tejun Heo3e087b52006-01-06 09:57:31 +0100655static void update_ordered(ide_drive_t *drive)
656{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200657 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100658 unsigned ordered = QUEUE_ORDERED_NONE;
659 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100660
661 if (drive->wcache) {
662 unsigned long long capacity;
663 int barrier;
664 /*
665 * We must avoid issuing commands a drive does not
666 * understand or we may crash it. We check flush cache
667 * is supported. We also check we have the LBA48 flush
668 * cache if the drive capacity is too large. By this
669 * time we have trimmed the drive capacity if LBA48 is
670 * not available so we don't need to recheck that.
671 */
672 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200673 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100674 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
675 ide_id_has_flush_cache_ext(id));
676
677 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800678 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100679
680 if (barrier) {
681 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
682 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100683 }
684 } else
685 ordered = QUEUE_ORDERED_DRAIN;
686
687 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100688}
689
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690static int write_cache(ide_drive_t *drive, int arg)
691{
692 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100693 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200695 if (arg < 0 || arg > 1)
696 return -EINVAL;
697
Tejun Heo3e087b52006-01-06 09:57:31 +0100698 if (ide_id_has_flush_cache(drive->id)) {
699 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100700 args.tf.feature = arg ?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100702 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100703 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100704 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100705 if (err == 0)
706 drive->wcache = arg;
707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Tejun Heo3e087b52006-01-06 09:57:31 +0100709 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Tejun Heo3e087b52006-01-06 09:57:31 +0100711 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712}
713
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200714static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
716 ide_task_t args;
717
718 memset(&args, 0, sizeof(ide_task_t));
719 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100720 args.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 else
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100722 args.tf.command = WIN_FLUSH_CACHE;
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 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200727static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
729 ide_task_t args;
730
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200731 if (arg < 0 || arg > 254)
732 return -EINVAL;
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100735 args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
736 args.tf.nsect = arg;
737 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100738 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100739 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 drive->acoustic = arg;
741 return 0;
742}
743
744/*
745 * drive->addressing:
746 * 0: 28-bit
747 * 1: 48-bit
748 * 2: 48-bit capable doing 28-bit
749 */
750static int set_lba_addressing(ide_drive_t *drive, int arg)
751{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200752 if (arg < 0 || arg > 2)
753 return -EINVAL;
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 drive->addressing = 0;
756
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200757 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return 0;
759
760 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200761 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 drive->addressing = arg;
763 return 0;
764}
765
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200766#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767static void idedisk_add_settings(ide_drive_t *drive)
768{
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200769 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
770 &drive->bios_cyl, NULL);
771 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
772 &drive->bios_head, NULL);
773 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
774 &drive->bios_sect, NULL);
775 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
776 &drive->addressing, set_lba_addressing);
777 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200778 drive->driveid->max_multsect, 1, 1, &drive->mult_count,
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200779 set_multcount);
780 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
781 &drive->nowerr, set_nowerr);
782 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
783 &drive->lun, NULL);
784 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
785 &drive->wcache, write_cache);
786 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
787 &drive->acoustic, set_acoustic);
788 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
789 &drive->failures, NULL);
790 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
791 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200793#else
794static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
795#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200797static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200799 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200800 u16 *id = drive->id;
801 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 idedisk_add_settings(drive);
805
806 if (drive->id_read == 0)
807 return;
808
Richard Purdie98109332006-02-03 03:04:55 -0800809 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200811 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200813 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 }
816
817 (void)set_lba_addressing(drive, 1);
818
819 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 int max_s = 2048;
821
822 if (max_s > hwif->rqsize)
823 max_s = hwif->rqsize;
824
825 blk_queue_max_sectors(drive->queue, max_s);
826 }
827
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200828 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
829 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
831 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200832 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
834 /* limit drive capacity to 137GB if LBA48 cannot be used */
835 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
836 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
837 "%llu sectors (%llu MB)\n",
838 drive->name, (unsigned long long)drive->capacity64,
839 sectors_to_MB(drive->capacity64));
840 drive->capacity64 = 1ULL << 28;
841 }
842
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200843 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200845 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
846 " will be used for accessing sectors "
847 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 } else
849 drive->addressing = 0;
850 }
851
852 /*
853 * if possible, give fdisk access to more of the drive,
854 * by correcting bios_cyls:
855 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200856 capacity = idedisk_capacity(drive);
857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 if (!drive->forced_geom) {
859
860 if (idedisk_supports_lba48(drive->id)) {
861 /* compatibility */
862 drive->bios_sect = 63;
863 drive->bios_head = 255;
864 }
865
866 if (drive->bios_sect && drive->bios_head) {
867 unsigned int cap0 = capacity; /* truncate to 32 bits */
868 unsigned int cylsz, cyl;
869
870 if (cap0 != capacity)
871 drive->bios_cyl = 65535;
872 else {
873 cylsz = drive->bios_sect * drive->bios_head;
874 cyl = cap0 / cylsz;
875 if (cyl > 65535)
876 cyl = 65535;
877 if (cyl > drive->bios_cyl)
878 drive->bios_cyl = cyl;
879 }
880 }
881 }
882 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
883 drive->name, capacity, sectors_to_MB(capacity));
884
885 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200886 if (id[ATA_ID_BUF_SIZE])
887 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100889 printk(KERN_CONT ", CHS=%d/%d/%d\n",
890 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 /* write cache enabled? */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200893 if ((id[ATA_ID_CSFO] & 1) || (id[ATA_ID_CFS_ENABLE_1] & (1 << 5)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 drive->wcache = 1;
895
896 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897}
898
899static void ide_cacheflush_p(ide_drive_t *drive)
900{
901 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
902 return;
903
904 if (do_idedisk_flushcache(drive))
905 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
906}
907
Russell King4031bbe2006-01-06 11:41:00 +0000908static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 struct ide_disk_obj *idkp = drive->driver_data;
911 struct gendisk *g = idkp->disk;
912
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200913 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 del_gendisk(g);
916
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100917 ide_cacheflush_p(drive);
918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920}
921
922static void ide_disk_release(struct kref *kref)
923{
924 struct ide_disk_obj *idkp = to_ide_disk(kref);
925 ide_drive_t *drive = idkp->drive;
926 struct gendisk *g = idkp->disk;
927
928 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 g->private_data = NULL;
930 put_disk(g);
931 kfree(idkp);
932}
933
Russell King4031bbe2006-01-06 11:41:00 +0000934static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Lee Trager0d2157f2007-06-08 15:14:30 +0200936/*
937 * On HPA drives the capacity needs to be
938 * reinitilized on resume otherwise the disk
939 * can not be used and a hard reset is required
940 */
941static void ide_disk_resume(ide_drive_t *drive)
942{
943 if (idedisk_supports_hpa(drive->id))
944 init_idedisk_capacity(drive);
945}
946
Russell King4031bbe2006-01-06 11:41:00 +0000947static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949#ifdef CONFIG_ALPHA
950 /* On Alpha, halt(8) doesn't actually turn the machine off,
951 it puts you into the sort of firmware monitor. Typically,
952 it's used to boot another kernel image, so it's not much
953 different from reboot(8). Therefore, we don't need to
954 spin down the disk in this case, especially since Alpha
955 firmware doesn't handle disks in standby mode properly.
956 On the other hand, it's reasonably safe to turn the power
957 off when the shutdown process reaches the firmware prompt,
958 as the firmware initialization takes rather long time -
959 at least 10 seconds, which should be sufficient for
960 the disk to expire its write cache. */
961 if (system_state != SYSTEM_POWER_OFF) {
962#else
963 if (system_state == SYSTEM_RESTART) {
964#endif
965 ide_cacheflush_p(drive);
966 return;
967 }
968
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100969 printk(KERN_INFO "Shutdown: %s\n", drive->name);
970
Russell King4031bbe2006-01-06 11:41:00 +0000971 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972}
973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100976 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200977 .name = "ide-disk",
978 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 },
Russell King4031bbe2006-01-06 11:41:00 +0000980 .probe = ide_disk_probe,
981 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200982 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000983 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 .version = IDEDISK_VERSION,
985 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 .do_request = ide_do_rw_disk,
988 .end_request = ide_end_request,
989 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200990#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200992#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993};
994
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100995static int idedisk_set_doorlock(ide_drive_t *drive, int on)
996{
997 ide_task_t task;
998
999 memset(&task, 0, sizeof(task));
1000 task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +01001001 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001002
1003 return ide_no_data_taskfile(drive, &task);
1004}
1005
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006static int idedisk_open(struct inode *inode, struct file *filp)
1007{
1008 struct gendisk *disk = inode->i_bdev->bd_disk;
1009 struct ide_disk_obj *idkp;
1010 ide_drive_t *drive;
1011
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001012 idkp = ide_disk_get(disk);
1013 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return -ENXIO;
1015
1016 drive = idkp->drive;
1017
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001018 idkp->openers++;
1019
1020 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 check_disk_change(inode->i_bdev);
1022 /*
1023 * Ignore the return code from door_lock,
1024 * since the open() has already succeeded,
1025 * and the door_lock is irrelevant at this point.
1026 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001027 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 drive->doorlocking = 0;
1029 }
1030 return 0;
1031}
1032
1033static int idedisk_release(struct inode *inode, struct file *filp)
1034{
1035 struct gendisk *disk = inode->i_bdev->bd_disk;
1036 struct ide_disk_obj *idkp = ide_disk_g(disk);
1037 ide_drive_t *drive = idkp->drive;
1038
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001039 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001041
1042 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001043 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 drive->doorlocking = 0;
1045 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001046
1047 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049 ide_disk_put(idkp);
1050
1051 return 0;
1052}
1053
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001054static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1055{
1056 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1057 ide_drive_t *drive = idkp->drive;
1058
1059 geo->heads = drive->bios_head;
1060 geo->sectors = drive->bios_sect;
1061 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1062 return 0;
1063}
1064
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065static int idedisk_ioctl(struct inode *inode, struct file *file,
1066 unsigned int cmd, unsigned long arg)
1067{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001068 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 struct block_device *bdev = inode->i_bdev;
1070 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001071 ide_drive_t *drive = idkp->drive;
1072 int err, (*setfunc)(ide_drive_t *, int);
1073 u8 *val;
1074
1075 switch (cmd) {
1076 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1077 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1078 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1079 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1080 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1081 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1082 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1083 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1084 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1085 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1086 }
1087
1088 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1089
1090read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001091 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001092 spin_lock_irqsave(&ide_lock, flags);
1093 err = *val;
1094 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001095 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001096 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1097
1098set_val:
1099 if (bdev != bdev->bd_contains)
1100 err = -EINVAL;
1101 else {
1102 if (!capable(CAP_SYS_ADMIN))
1103 err = -EACCES;
1104 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001105 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001106 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001107 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001108 }
1109 }
1110 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
1113static int idedisk_media_changed(struct gendisk *disk)
1114{
1115 struct ide_disk_obj *idkp = ide_disk_g(disk);
1116 ide_drive_t *drive = idkp->drive;
1117
1118 /* do not scan partitions twice if this is a removable device */
1119 if (drive->attach) {
1120 drive->attach = 0;
1121 return 0;
1122 }
1123 /* if removable, always assume it was changed */
1124 return drive->removable;
1125}
1126
1127static int idedisk_revalidate_disk(struct gendisk *disk)
1128{
1129 struct ide_disk_obj *idkp = ide_disk_g(disk);
1130 set_capacity(disk, idedisk_capacity(idkp->drive));
1131 return 0;
1132}
1133
1134static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001135 .owner = THIS_MODULE,
1136 .open = idedisk_open,
1137 .release = idedisk_release,
1138 .ioctl = idedisk_ioctl,
1139 .getgeo = idedisk_getgeo,
1140 .media_changed = idedisk_media_changed,
1141 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142};
1143
1144MODULE_DESCRIPTION("ATA DISK Driver");
1145
Russell King4031bbe2006-01-06 11:41:00 +00001146static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147{
1148 struct ide_disk_obj *idkp;
1149 struct gendisk *g;
1150
1151 /* strstr("foo", "") is non-NULL */
1152 if (!strstr("ide-disk", drive->driver_req))
1153 goto failed;
1154 if (!drive->present)
1155 goto failed;
1156 if (drive->media != ide_disk)
1157 goto failed;
1158
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001159 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 if (!idkp)
1161 goto failed;
1162
Tejun Heo689d6fa2008-08-25 19:56:16 +09001163 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 if (!g)
1165 goto out_free_idkp;
1166
1167 ide_init_disk(g, drive);
1168
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001169 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 kref_init(&idkp->kref);
1172
1173 idkp->drive = drive;
1174 idkp->driver = &idedisk_driver;
1175 idkp->disk = g;
1176
1177 g->private_data = &idkp->driver;
1178
1179 drive->driver_data = idkp;
1180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 idedisk_setup(drive);
1182 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1183 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1184 drive->name, drive->head);
1185 drive->attach = 0;
1186 } else
1187 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001188
Tejun Heof615b482008-08-25 19:47:24 +09001189 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001191 g->flags |= GENHD_FL_EXT_DEVT;
1192 if (drive->removable)
1193 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 set_capacity(g, idedisk_capacity(drive));
1195 g->fops = &idedisk_ops;
1196 add_disk(g);
1197 return 0;
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199out_free_idkp:
1200 kfree(idkp);
1201failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001202 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203}
1204
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001205static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001207 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208}
1209
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001210static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001212 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213}
1214
Kay Sievers263756e2005-12-12 18:03:44 +01001215MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216module_init(idedisk_init);
1217module_exit(idedisk_exit);
1218MODULE_LICENSE("GPL");