blob: 8f1ec037309a94b84b4fa3463a381f4054593045 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Bartlomiej Zolnierkiewicz59bca8c2008-02-01 23:09:33 +01002 * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
3 * Copyright (C) 1998-2002 Linux ATA Development
4 * Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2003 Red Hat <alan@redhat.com>
6 * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
9/*
10 * Mostly written by Mark Lord <mlord@pobox.com>
11 * and Gadi Oxman <gadio@netvision.net.il>
12 * and Andre Hedrick <andre@linux-ide.org>
13 *
14 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 */
16
17#define IDEDISK_VERSION "1.18"
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/mm.h>
25#include <linux/interrupt.h>
26#include <linux/major.h>
27#include <linux/errno.h>
28#include <linux/genhd.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080031#include <linux/mutex.h>
Richard Purdie2bfb6462006-03-31 02:31:16 -080032#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#define _IDE_DISK
35
36#include <linux/ide.h>
37
38#include <asm/byteorder.h>
39#include <asm/irq.h>
40#include <asm/uaccess.h>
41#include <asm/io.h>
42#include <asm/div64.h>
43
Tejun Heo870d6652008-08-25 19:47:25 +090044#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
Tejun Heo689d6fa2008-08-25 19:56:16 +090045#define IDE_DISK_MINORS (1 << PARTN_BITS)
Tejun Heo870d6652008-08-25 19:47:25 +090046#else
Tejun Heo3e1a7ff2008-08-25 19:56:17 +090047#define IDE_DISK_MINORS 0
Tejun Heo870d6652008-08-25 19:47:25 +090048#endif
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050struct ide_disk_obj {
51 ide_drive_t *drive;
52 ide_driver_t *driver;
53 struct gendisk *disk;
54 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010055 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056};
57
Arjan van de Vencf8b8972006-03-23 03:00:45 -080058static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
61
62#define ide_disk_g(disk) \
63 container_of((disk)->private_data, struct ide_disk_obj, driver)
64
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020065static void ide_disk_release(struct kref *);
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
68{
69 struct ide_disk_obj *idkp = NULL;
70
Arjan van de Vencf8b8972006-03-23 03:00:45 -080071 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020073 if (idkp) {
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020074 if (ide_device_get(idkp->drive))
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020075 idkp = NULL;
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020076 else
77 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020078 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080079 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return idkp;
81}
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083static void ide_disk_put(struct ide_disk_obj *idkp)
84{
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020085 ide_drive_t *drive = idkp->drive;
86
Arjan van de Vencf8b8972006-03-23 03:00:45 -080087 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 kref_put(&idkp->kref, ide_disk_release);
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020089 ide_device_put(drive);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080090 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
92
93/*
94 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
95 * value for this drive (from its reported identification information).
96 *
97 * Returns: 1 if lba_capacity looks sensible
98 * 0 otherwise
99 *
100 * It is called only once for each drive.
101 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200102static int lba_capacity_is_ok(u16 *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103{
104 unsigned long lba_sects, chs_sects, head, tail;
105
Alan Cox6efd9362005-06-27 15:24:22 -0700106 /* No non-LBA info .. so valid! */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200107 if (id[ATA_ID_CYLS] == 0)
Alan Cox6efd9362005-06-27 15:24:22 -0700108 return 1;
109
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200110 lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 /*
113 * The ATA spec tells large drives to return
114 * C/H/S = 16383/16/63 independent of their size.
115 * Some drives can be jumpered to use 15 heads instead of 16.
116 * Some drives can be jumpered to use 4092 cyls instead of 16383.
117 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200118 if ((id[ATA_ID_CYLS] == 16383 ||
119 (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
120 id[ATA_ID_SECTORS] == 63 &&
121 (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200122 (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return 1;
124
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200125 chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 /* perform a rough sanity check on lba_sects: within 10% is OK */
128 if ((lba_sects - chs_sects) < chs_sects/10)
129 return 1;
130
131 /* some drives have the word order reversed */
132 head = ((lba_sects >> 16) & 0xffff);
133 tail = (lba_sects & 0xffff);
134 lba_sects = (head | (tail << 16));
135 if ((lba_sects - chs_sects) < chs_sects/10) {
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200136 *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 return 1; /* lba_capacity is (now) good */
138 }
139
140 return 0; /* lba_capacity value may be bad */
141}
142
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100143static const u8 ide_rw_cmds[] = {
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) &&
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200406 ata_id_u64(id, ATA_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 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 /*
461 * If this drive supports the Host Protected Area feature set,
462 * then we may need to change our opinion about the drive's capacity.
463 */
464 int hpa = idedisk_supports_hpa(id);
465
466 if (idedisk_supports_lba48(id)) {
467 /* drive speaks 48-bit LBA */
468 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200469 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 if (hpa)
471 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200472 } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 /* drive speaks 28-bit LBA */
474 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200475 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 if (hpa)
477 idedisk_check_hpa(drive);
478 } else {
479 /* drive speaks boring old 28-bit CHS */
480 drive->capacity64 = drive->cyl * drive->head * drive->sect;
481 }
482}
483
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200484static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 return drive->capacity64 - drive->sect0;
487}
488
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200489#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490static int smart_enable(ide_drive_t *drive)
491{
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 = SMART_ENABLE;
497 tf->lbam = SMART_LCYL_PASS;
498 tf->lbah = SMART_HCYL_PASS;
499 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100500 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100501 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200504static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
506 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100507 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100510 tf->feature = sub_cmd;
511 tf->nsect = 0x01;
512 tf->lbam = SMART_LCYL_PASS;
513 tf->lbah = SMART_HCYL_PASS;
514 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100515 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100516 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100518 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
521static int proc_idedisk_read_cache
522 (char *page, char **start, off_t off, int count, int *eof, void *data)
523{
524 ide_drive_t *drive = (ide_drive_t *) data;
525 char *out = page;
526 int len;
527
528 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200529 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200531 len = sprintf(out, "(none)\n");
532
533 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}
535
536static int proc_idedisk_read_capacity
537 (char *page, char **start, off_t off, int count, int *eof, void *data)
538{
539 ide_drive_t*drive = (ide_drive_t *)data;
540 int len;
541
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200542 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
543
544 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545}
546
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200547static int proc_idedisk_read_smart(char *page, char **start, off_t off,
548 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
550 ide_drive_t *drive = (ide_drive_t *)data;
551 int len = 0, i = 0;
552
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200553 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 unsigned short *val = (unsigned short *) page;
555 char *out = ((char *)val) + (SECTOR_WORDS * 4);
556 page = out;
557 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200558 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
559 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 val += 1;
561 } while (i < (SECTOR_WORDS * 2));
562 len = out - page;
563 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200564
565 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566}
567
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200568static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 (char *page, char **start, off_t off, int count, int *eof, void *data)
570{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200571 return proc_idedisk_read_smart(page, start, off, count, eof, data,
572 SMART_READ_VALUES);
573}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200575static int proc_idedisk_read_st
576 (char *page, char **start, off_t off, int count, int *eof, void *data)
577{
578 return proc_idedisk_read_smart(page, start, off, count, eof, data,
579 SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580}
581
582static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200583 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
584 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
585 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
586 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
587 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 { NULL, 0, NULL, NULL }
589};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200590#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Jens Axboe165125e2007-07-24 09:28:11 +0200592static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100595 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100597 /* FIXME: map struct ide_taskfile on rq->cmd[] */
598 BUG_ON(task == NULL);
599
600 memset(task, 0, sizeof(*task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 if (ide_id_has_flush_cache_ext(drive->id) &&
602 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100603 task->tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 else
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100605 task->tf.command = WIN_FLUSH_CACHE;
606 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
607 IDE_TFLAG_DYN;
608 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100610 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200611 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100612 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613}
614
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615/*
616 * This is tightly woven into the driver->do_special can not touch.
617 * DON'T do it again until a total personality rewrite is committed.
618 */
619static int set_multcount(ide_drive_t *drive, int arg)
620{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200621 struct request *rq;
622 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200624 if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200625 return -EINVAL;
626
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 if (drive->special.b.set_multmode)
628 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100629
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200630 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
631 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 drive->mult_req = arg;
634 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200635 error = blk_execute_rq(drive->queue, NULL, rq, 0);
636 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 return (drive->mult_count == arg) ? 0 : -EIO;
639}
640
641static int set_nowerr(ide_drive_t *drive, int arg)
642{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200643 if (arg < 0 || arg > 1)
644 return -EINVAL;
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 if (ide_spin_wait_hwgroup(drive))
647 return -EBUSY;
648 drive->nowerr = arg;
649 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
650 spin_unlock_irq(&ide_lock);
651 return 0;
652}
653
Tejun Heo3e087b52006-01-06 09:57:31 +0100654static void update_ordered(ide_drive_t *drive)
655{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200656 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100657 unsigned ordered = QUEUE_ORDERED_NONE;
658 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100659
660 if (drive->wcache) {
661 unsigned long long capacity;
662 int barrier;
663 /*
664 * We must avoid issuing commands a drive does not
665 * understand or we may crash it. We check flush cache
666 * is supported. We also check we have the LBA48 flush
667 * cache if the drive capacity is too large. By this
668 * time we have trimmed the drive capacity if LBA48 is
669 * not available so we don't need to recheck that.
670 */
671 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200672 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100673 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
674 ide_id_has_flush_cache_ext(id));
675
676 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800677 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100678
679 if (barrier) {
680 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
681 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100682 }
683 } else
684 ordered = QUEUE_ORDERED_DRAIN;
685
686 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100687}
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689static int write_cache(ide_drive_t *drive, int arg)
690{
691 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100692 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200694 if (arg < 0 || arg > 1)
695 return -EINVAL;
696
Tejun Heo3e087b52006-01-06 09:57:31 +0100697 if (ide_id_has_flush_cache(drive->id)) {
698 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100699 args.tf.feature = arg ?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100701 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100702 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100703 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100704 if (err == 0)
705 drive->wcache = arg;
706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Tejun Heo3e087b52006-01-06 09:57:31 +0100708 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Tejun Heo3e087b52006-01-06 09:57:31 +0100710 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711}
712
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200713static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 ide_task_t args;
716
717 memset(&args, 0, sizeof(ide_task_t));
718 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100719 args.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 else
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100721 args.tf.command = WIN_FLUSH_CACHE;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100722 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100723 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724}
725
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200726static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
728 ide_task_t args;
729
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200730 if (arg < 0 || arg > 254)
731 return -EINVAL;
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100734 args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
735 args.tf.nsect = arg;
736 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100737 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100738 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 drive->acoustic = arg;
740 return 0;
741}
742
743/*
744 * drive->addressing:
745 * 0: 28-bit
746 * 1: 48-bit
747 * 2: 48-bit capable doing 28-bit
748 */
749static int set_lba_addressing(ide_drive_t *drive, int arg)
750{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200751 if (arg < 0 || arg > 2)
752 return -EINVAL;
753
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 drive->addressing = 0;
755
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200756 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return 0;
758
759 if (!idedisk_supports_lba48(drive->id))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200760 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 drive->addressing = arg;
762 return 0;
763}
764
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200765#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766static void idedisk_add_settings(ide_drive_t *drive)
767{
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200768 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
769 &drive->bios_cyl, NULL);
770 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
771 &drive->bios_head, NULL);
772 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
773 &drive->bios_sect, NULL);
774 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
775 &drive->addressing, set_lba_addressing);
776 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200777 drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1,
778 &drive->mult_count, set_multcount);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200779 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
780 &drive->nowerr, set_nowerr);
781 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
782 &drive->lun, NULL);
783 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
784 &drive->wcache, write_cache);
785 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
786 &drive->acoustic, set_acoustic);
787 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
788 &drive->failures, NULL);
789 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
790 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200792#else
793static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
794#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200796static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200798 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200799 u16 *id = drive->id;
800 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803 idedisk_add_settings(drive);
804
805 if (drive->id_read == 0)
806 return;
807
Richard Purdie98109332006-02-03 03:04:55 -0800808 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200810 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200812 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 }
815
816 (void)set_lba_addressing(drive, 1);
817
818 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 int max_s = 2048;
820
821 if (max_s > hwif->rqsize)
822 max_s = hwif->rqsize;
823
824 blk_queue_max_sectors(drive->queue, max_s);
825 }
826
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200827 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
828 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
830 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200831 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 /* limit drive capacity to 137GB if LBA48 cannot be used */
834 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
835 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
836 "%llu sectors (%llu MB)\n",
837 drive->name, (unsigned long long)drive->capacity64,
838 sectors_to_MB(drive->capacity64));
839 drive->capacity64 = 1ULL << 28;
840 }
841
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200842 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200844 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
845 " will be used for accessing sectors "
846 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 } else
848 drive->addressing = 0;
849 }
850
851 /*
852 * if possible, give fdisk access to more of the drive,
853 * by correcting bios_cyls:
854 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200855 capacity = idedisk_capacity(drive);
856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 if (!drive->forced_geom) {
858
859 if (idedisk_supports_lba48(drive->id)) {
860 /* compatibility */
861 drive->bios_sect = 63;
862 drive->bios_head = 255;
863 }
864
865 if (drive->bios_sect && drive->bios_head) {
866 unsigned int cap0 = capacity; /* truncate to 32 bits */
867 unsigned int cylsz, cyl;
868
869 if (cap0 != capacity)
870 drive->bios_cyl = 65535;
871 else {
872 cylsz = drive->bios_sect * drive->bios_head;
873 cyl = cap0 / cylsz;
874 if (cyl > 65535)
875 cyl = 65535;
876 if (cyl > drive->bios_cyl)
877 drive->bios_cyl = cyl;
878 }
879 }
880 }
881 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
882 drive->name, capacity, sectors_to_MB(capacity));
883
884 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200885 if (id[ATA_ID_BUF_SIZE])
886 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100888 printk(KERN_CONT ", CHS=%d/%d/%d\n",
889 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* write cache enabled? */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200892 if ((id[ATA_ID_CSFO] & 1) || (id[ATA_ID_CFS_ENABLE_1] & (1 << 5)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 drive->wcache = 1;
894
895 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896}
897
898static void ide_cacheflush_p(ide_drive_t *drive)
899{
900 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
901 return;
902
903 if (do_idedisk_flushcache(drive))
904 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
905}
906
Russell King4031bbe2006-01-06 11:41:00 +0000907static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
909 struct ide_disk_obj *idkp = drive->driver_data;
910 struct gendisk *g = idkp->disk;
911
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200912 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 del_gendisk(g);
915
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100916 ide_cacheflush_p(drive);
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919}
920
921static void ide_disk_release(struct kref *kref)
922{
923 struct ide_disk_obj *idkp = to_ide_disk(kref);
924 ide_drive_t *drive = idkp->drive;
925 struct gendisk *g = idkp->disk;
926
927 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 g->private_data = NULL;
929 put_disk(g);
930 kfree(idkp);
931}
932
Russell King4031bbe2006-01-06 11:41:00 +0000933static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
Lee Trager0d2157f2007-06-08 15:14:30 +0200935/*
936 * On HPA drives the capacity needs to be
937 * reinitilized on resume otherwise the disk
938 * can not be used and a hard reset is required
939 */
940static void ide_disk_resume(ide_drive_t *drive)
941{
942 if (idedisk_supports_hpa(drive->id))
943 init_idedisk_capacity(drive);
944}
945
Russell King4031bbe2006-01-06 11:41:00 +0000946static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948#ifdef CONFIG_ALPHA
949 /* On Alpha, halt(8) doesn't actually turn the machine off,
950 it puts you into the sort of firmware monitor. Typically,
951 it's used to boot another kernel image, so it's not much
952 different from reboot(8). Therefore, we don't need to
953 spin down the disk in this case, especially since Alpha
954 firmware doesn't handle disks in standby mode properly.
955 On the other hand, it's reasonably safe to turn the power
956 off when the shutdown process reaches the firmware prompt,
957 as the firmware initialization takes rather long time -
958 at least 10 seconds, which should be sufficient for
959 the disk to expire its write cache. */
960 if (system_state != SYSTEM_POWER_OFF) {
961#else
962 if (system_state == SYSTEM_RESTART) {
963#endif
964 ide_cacheflush_p(drive);
965 return;
966 }
967
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100968 printk(KERN_INFO "Shutdown: %s\n", drive->name);
969
Russell King4031bbe2006-01-06 11:41:00 +0000970 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971}
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100975 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200976 .name = "ide-disk",
977 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 },
Russell King4031bbe2006-01-06 11:41:00 +0000979 .probe = ide_disk_probe,
980 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200981 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000982 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 .version = IDEDISK_VERSION,
984 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 .do_request = ide_do_rw_disk,
987 .end_request = ide_end_request,
988 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200989#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200991#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992};
993
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100994static int idedisk_set_doorlock(ide_drive_t *drive, int on)
995{
996 ide_task_t task;
997
998 memset(&task, 0, sizeof(task));
999 task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +01001000 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001001
1002 return ide_no_data_taskfile(drive, &task);
1003}
1004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005static int idedisk_open(struct inode *inode, struct file *filp)
1006{
1007 struct gendisk *disk = inode->i_bdev->bd_disk;
1008 struct ide_disk_obj *idkp;
1009 ide_drive_t *drive;
1010
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001011 idkp = ide_disk_get(disk);
1012 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return -ENXIO;
1014
1015 drive = idkp->drive;
1016
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001017 idkp->openers++;
1018
1019 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 check_disk_change(inode->i_bdev);
1021 /*
1022 * Ignore the return code from door_lock,
1023 * since the open() has already succeeded,
1024 * and the door_lock is irrelevant at this point.
1025 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001026 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 drive->doorlocking = 0;
1028 }
1029 return 0;
1030}
1031
1032static int idedisk_release(struct inode *inode, struct file *filp)
1033{
1034 struct gendisk *disk = inode->i_bdev->bd_disk;
1035 struct ide_disk_obj *idkp = ide_disk_g(disk);
1036 ide_drive_t *drive = idkp->drive;
1037
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001038 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001040
1041 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001042 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 drive->doorlocking = 0;
1044 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001045
1046 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 ide_disk_put(idkp);
1049
1050 return 0;
1051}
1052
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001053static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1054{
1055 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1056 ide_drive_t *drive = idkp->drive;
1057
1058 geo->heads = drive->bios_head;
1059 geo->sectors = drive->bios_sect;
1060 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1061 return 0;
1062}
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064static int idedisk_ioctl(struct inode *inode, struct file *file,
1065 unsigned int cmd, unsigned long arg)
1066{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001067 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 struct block_device *bdev = inode->i_bdev;
1069 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001070 ide_drive_t *drive = idkp->drive;
1071 int err, (*setfunc)(ide_drive_t *, int);
1072 u8 *val;
1073
1074 switch (cmd) {
1075 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1076 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1077 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1078 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1079 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1080 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1081 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1082 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1083 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1084 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1085 }
1086
1087 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1088
1089read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001090 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001091 spin_lock_irqsave(&ide_lock, flags);
1092 err = *val;
1093 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001094 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001095 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1096
1097set_val:
1098 if (bdev != bdev->bd_contains)
1099 err = -EINVAL;
1100 else {
1101 if (!capable(CAP_SYS_ADMIN))
1102 err = -EACCES;
1103 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001104 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001105 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001106 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001107 }
1108 }
1109 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
1112static int idedisk_media_changed(struct gendisk *disk)
1113{
1114 struct ide_disk_obj *idkp = ide_disk_g(disk);
1115 ide_drive_t *drive = idkp->drive;
1116
1117 /* do not scan partitions twice if this is a removable device */
1118 if (drive->attach) {
1119 drive->attach = 0;
1120 return 0;
1121 }
1122 /* if removable, always assume it was changed */
1123 return drive->removable;
1124}
1125
1126static int idedisk_revalidate_disk(struct gendisk *disk)
1127{
1128 struct ide_disk_obj *idkp = ide_disk_g(disk);
1129 set_capacity(disk, idedisk_capacity(idkp->drive));
1130 return 0;
1131}
1132
1133static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001134 .owner = THIS_MODULE,
1135 .open = idedisk_open,
1136 .release = idedisk_release,
1137 .ioctl = idedisk_ioctl,
1138 .getgeo = idedisk_getgeo,
1139 .media_changed = idedisk_media_changed,
1140 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141};
1142
1143MODULE_DESCRIPTION("ATA DISK Driver");
1144
Russell King4031bbe2006-01-06 11:41:00 +00001145static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
1147 struct ide_disk_obj *idkp;
1148 struct gendisk *g;
1149
1150 /* strstr("foo", "") is non-NULL */
1151 if (!strstr("ide-disk", drive->driver_req))
1152 goto failed;
1153 if (!drive->present)
1154 goto failed;
1155 if (drive->media != ide_disk)
1156 goto failed;
1157
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001158 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 if (!idkp)
1160 goto failed;
1161
Tejun Heo689d6fa2008-08-25 19:56:16 +09001162 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (!g)
1164 goto out_free_idkp;
1165
1166 ide_init_disk(g, drive);
1167
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001168 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 kref_init(&idkp->kref);
1171
1172 idkp->drive = drive;
1173 idkp->driver = &idedisk_driver;
1174 idkp->disk = g;
1175
1176 g->private_data = &idkp->driver;
1177
1178 drive->driver_data = idkp;
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 idedisk_setup(drive);
1181 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1182 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1183 drive->name, drive->head);
1184 drive->attach = 0;
1185 } else
1186 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001187
Tejun Heof615b482008-08-25 19:47:24 +09001188 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001190 g->flags |= GENHD_FL_EXT_DEVT;
1191 if (drive->removable)
1192 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 set_capacity(g, idedisk_capacity(drive));
1194 g->fops = &idedisk_ops;
1195 add_disk(g);
1196 return 0;
1197
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198out_free_idkp:
1199 kfree(idkp);
1200failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001201 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202}
1203
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001204static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001206 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207}
1208
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001209static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001211 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212}
1213
Kay Sievers263756e2005-12-12 18:03:44 +01001214MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215module_init(idedisk_init);
1216module_exit(idedisk_exit);
1217MODULE_LICENSE("GPL");