blob: 43025c9d8355c857a408acc9beb302c2315c9511 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Bartlomiej Zolnierkiewicz59bca8c2008-02-01 23:09:33 +01002 * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
3 * Copyright (C) 1998-2002 Linux ATA Development
4 * Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2003 Red Hat <alan@redhat.com>
6 * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
9/*
10 * Mostly written by Mark Lord <mlord@pobox.com>
11 * and Gadi Oxman <gadio@netvision.net.il>
12 * and Andre Hedrick <andre@linux-ide.org>
13 *
14 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 */
16
17#define IDEDISK_VERSION "1.18"
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/mm.h>
25#include <linux/interrupt.h>
26#include <linux/major.h>
27#include <linux/errno.h>
28#include <linux/genhd.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080031#include <linux/mutex.h>
Richard Purdie2bfb6462006-03-31 02:31:16 -080032#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/ide.h>
Bartlomiej Zolnierkiewicz3ceca722008-10-10 22:39:27 +020034#include <linux/hdreg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#include <asm/byteorder.h>
37#include <asm/irq.h>
38#include <asm/uaccess.h>
39#include <asm/io.h>
40#include <asm/div64.h>
41
Tejun Heo870d6652008-08-25 19:47:25 +090042#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
Tejun Heo689d6fa2008-08-25 19:56:16 +090043#define IDE_DISK_MINORS (1 << PARTN_BITS)
Tejun Heo870d6652008-08-25 19:47:25 +090044#else
Tejun Heo3e1a7ff2008-08-25 19:56:17 +090045#define IDE_DISK_MINORS 0
Tejun Heo870d6652008-08-25 19:47:25 +090046#endif
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048struct ide_disk_obj {
49 ide_drive_t *drive;
50 ide_driver_t *driver;
51 struct gendisk *disk;
52 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010053 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
Arjan van de Vencf8b8972006-03-23 03:00:45 -080056static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
59
60#define ide_disk_g(disk) \
61 container_of((disk)->private_data, struct ide_disk_obj, driver)
62
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020063static void ide_disk_release(struct kref *);
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
66{
67 struct ide_disk_obj *idkp = NULL;
68
Arjan van de Vencf8b8972006-03-23 03:00:45 -080069 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 idkp = ide_disk_g(disk);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020071 if (idkp) {
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020072 if (ide_device_get(idkp->drive))
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020073 idkp = NULL;
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020074 else
75 kref_get(&idkp->kref);
Bartlomiej Zolnierkiewicz08da5912008-07-24 22:53:15 +020076 }
Arjan van de Vencf8b8972006-03-23 03:00:45 -080077 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return idkp;
79}
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static void ide_disk_put(struct ide_disk_obj *idkp)
82{
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020083 ide_drive_t *drive = idkp->drive;
84
Arjan van de Vencf8b8972006-03-23 03:00:45 -080085 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 kref_put(&idkp->kref, ide_disk_release);
Bartlomiej Zolnierkiewiczd3e33ff2008-08-05 18:16:59 +020087 ide_device_put(drive);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080088 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089}
90
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +010091static const u8 ide_rw_cmds[] = {
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +020092 ATA_CMD_READ_MULTI,
93 ATA_CMD_WRITE_MULTI,
94 ATA_CMD_READ_MULTI_EXT,
95 ATA_CMD_WRITE_MULTI_EXT,
96 ATA_CMD_PIO_READ,
97 ATA_CMD_PIO_WRITE,
98 ATA_CMD_PIO_READ_EXT,
99 ATA_CMD_PIO_WRITE_EXT,
100 ATA_CMD_READ,
101 ATA_CMD_WRITE,
102 ATA_CMD_READ_EXT,
103 ATA_CMD_WRITE_EXT,
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100104};
105
106static const u8 ide_data_phases[] = {
107 TASKFILE_MULTI_IN,
108 TASKFILE_MULTI_OUT,
109 TASKFILE_IN,
110 TASKFILE_OUT,
111 TASKFILE_IN_DMA,
112 TASKFILE_OUT_DMA,
113};
114
115static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
116{
117 u8 index, lba48, write;
118
119 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
120 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
121
122 if (dma)
Bartlomiej Zolnierkiewiczba4b2e62008-07-23 19:55:55 +0200123 index = 8;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100124 else
125 index = drive->mult_count ? 0 : 4;
126
127 task->tf.command = ide_rw_cmds[index + lba48 + write];
128
129 if (dma)
130 index = 8; /* fixup index */
131
132 task->data_phase = ide_data_phases[index / 2 + write];
133}
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/*
136 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
137 * using LBA if supported, or CHS otherwise, to address sectors.
138 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200139static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
140 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
142 ide_hwif_t *hwif = HWIF(drive);
143 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100144 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100146 ide_task_t task;
147 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100148 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200150 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 if (block + rq->nr_sectors > 1ULL << 28)
152 dma = 0;
153 else
154 lba48 = 0;
155 }
156
157 if (!dma) {
158 ide_init_sg_cmd(drive, rq);
159 ide_map_sg(drive, rq);
160 }
161
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100162 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewicz9a410e72008-07-15 21:21:48 +0200163 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 if (drive->select.b.lba) {
166 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800167 pr_debug("%s: LBA=0x%012llx\n", drive->name,
168 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100170 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100171 tf->hob_lbal = (u8)(block >> 24);
172 if (sizeof(block) != 4) {
173 tf->hob_lbam = (u8)((u64)block >> 32);
174 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100176
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100177 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100178 tf->lbal = (u8) block;
179 tf->lbam = (u8)(block >> 8);
180 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100181
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100182 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100184 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100185 tf->lbal = block;
186 tf->lbam = block >>= 8;
187 tf->lbah = block >>= 8;
188 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 }
190 } else {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200191 unsigned int sect, head, cyl, track;
192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 track = (int)block / drive->sect;
194 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 head = track % drive->head;
196 cyl = track / drive->head;
197
198 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
199
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100200 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100201 tf->lbal = sect;
202 tf->lbam = cyl;
203 tf->lbah = cyl >> 8;
204 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 }
206
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100207 if (rq_data_dir(rq))
208 task.tf_flags |= IDE_TFLAG_WRITE;
209
210 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100211 if (!dma)
212 hwif->data_phase = task.data_phase;
213 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100214
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100215 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100216
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100217 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100219 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100220 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100221 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100223 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 }
225
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100226 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227}
228
229/*
230 * 268435455 == 137439 MB or 28bit limit
231 * 320173056 == 163929 MB or 48bit addressing
232 * 1073741822 == 549756 MB or 48bit addressing fake drive
233 */
234
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200235static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
236 sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 ide_hwif_t *hwif = HWIF(drive);
239
240 BUG_ON(drive->blocked);
241
242 if (!blk_fs_request(rq)) {
243 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
244 ide_end_request(drive, 0, 0);
245 return ide_stopped;
246 }
247
Richard Purdie2bfb6462006-03-31 02:31:16 -0800248 ledtrig_ide_activity();
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
251 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800252 (unsigned long long)block, rq->nr_sectors,
253 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 if (hwif->rw_disk)
256 hwif->rw_disk(drive, rq);
257
258 return __ide_do_rw_disk(drive, rq, block);
259}
260
261/*
262 * Queries for true maximum capacity of the drive.
263 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
264 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100265static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100268 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100269 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 /* Create IDE/ATA command request structure */
272 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100273 if (lba48)
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200274 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100275 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200276 tf->command = ATA_CMD_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100277 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100278 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100279 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100280 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100282 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100285 if ((tf->status & 0x01) == 0)
286 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 return addr;
289}
290
291/*
292 * Sets maximum virtual LBA address of the drive.
293 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
294 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100295static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296{
297 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100298 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100299 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 addr_req--;
302 /* Create IDE/ATA command request structure */
303 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100304 tf->lbal = (addr_req >> 0) & 0xff;
305 tf->lbam = (addr_req >>= 8) & 0xff;
306 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100307 if (lba48) {
308 tf->hob_lbal = (addr_req >>= 8) & 0xff;
309 tf->hob_lbam = (addr_req >>= 8) & 0xff;
310 tf->hob_lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200311 tf->command = ATA_CMD_SET_MAX_EXT;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100312 } else {
313 tf->device = (addr_req >>= 8) & 0x0f;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200314 tf->command = ATA_CMD_SET_MAX;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100315 }
316 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100317 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100318 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100319 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100321 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100323 if ((tf->status & 0x01) == 0)
324 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 return addr_set;
327}
328
329static unsigned long long sectors_to_MB(unsigned long long n)
330{
331 n <<= 9; /* make it bytes */
332 do_div(n, 1000000); /* make it MB */
333 return n;
334}
335
336/*
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200337 * Some disks report total number of sectors instead of
338 * maximum sector address. We list them here.
339 */
340static const struct drive_list_entry hpa_list[] = {
341 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200342 { "ST320413A", NULL },
Mikko Rapelib152fcd2008-02-19 01:41:25 +0100343 { "ST310211A", NULL },
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200344 { NULL, NULL }
345};
346
Arjan van de Ven858119e2006-01-14 13:20:43 -0800347static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
349 unsigned long long capacity, set_max;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200350 int lba48 = ata_id_lba48_enabled(drive->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100353
354 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Bartlomiej Zolnierkiewiczb0244a02007-08-20 22:42:57 +0200356 if (ide_in_drive_list(drive->id, hpa_list)) {
357 /*
358 * Since we are inclusive wrt to firmware revisions do this
359 * extra check and apply the workaround only when needed.
360 */
361 if (set_max == capacity + 1)
362 set_max--;
363 }
364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (set_max <= capacity)
366 return;
367
368 printk(KERN_INFO "%s: Host Protected Area detected.\n"
369 "\tcurrent capacity is %llu sectors (%llu MB)\n"
370 "\tnative capacity is %llu sectors (%llu MB)\n",
371 drive->name,
372 capacity, sectors_to_MB(capacity),
373 set_max, sectors_to_MB(set_max));
374
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100375 set_max = idedisk_set_max_address(drive, set_max, lba48);
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (set_max) {
378 drive->capacity64 = set_max;
379 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
380 drive->name);
381 }
382}
383
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200384static void init_idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200386 u16 *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 /*
388 * If this drive supports the Host Protected Area feature set,
389 * then we may need to change our opinion about the drive's capacity.
390 */
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200391 int hpa = ata_id_hpa_enabled(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200393 if (ata_id_lba48_enabled(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 /* drive speaks 48-bit LBA */
395 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200396 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 if (hpa)
398 idedisk_check_hpa(drive);
Bartlomiej Zolnierkiewicza02227c92008-10-10 22:39:31 +0200399 } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 /* drive speaks 28-bit LBA */
401 drive->select.b.lba = 1;
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200402 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 if (hpa)
404 idedisk_check_hpa(drive);
405 } else {
406 /* drive speaks boring old 28-bit CHS */
407 drive->capacity64 = drive->cyl * drive->head * drive->sect;
408 }
409}
410
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200411static sector_t idedisk_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
Bartlomiej Zolnierkiewicz3c619ff2008-10-10 22:39:22 +0200413 return drive->capacity64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200416#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417static int smart_enable(ide_drive_t *drive)
418{
419 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100420 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200423 tf->feature = ATA_SMART_ENABLE;
424 tf->lbam = ATA_SMART_LBAM_PASS;
425 tf->lbah = ATA_SMART_LBAH_PASS;
426 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100427 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100428 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200431static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100434 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100437 tf->feature = sub_cmd;
438 tf->nsect = 0x01;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200439 tf->lbam = ATA_SMART_LBAM_PASS;
440 tf->lbah = ATA_SMART_LBAH_PASS;
441 tf->command = ATA_CMD_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100442 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100443 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100445 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
448static int proc_idedisk_read_cache
449 (char *page, char **start, off_t off, int count, int *eof, void *data)
450{
451 ide_drive_t *drive = (ide_drive_t *) data;
452 char *out = page;
453 int len;
454
455 if (drive->id_read)
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200456 len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 else
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200458 len = sprintf(out, "(none)\n");
459
460 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461}
462
463static int proc_idedisk_read_capacity
464 (char *page, char **start, off_t off, int count, int *eof, void *data)
465{
466 ide_drive_t*drive = (ide_drive_t *)data;
467 int len;
468
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200469 len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
470
471 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472}
473
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200474static int proc_idedisk_read_smart(char *page, char **start, off_t off,
475 int count, int *eof, void *data, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
477 ide_drive_t *drive = (ide_drive_t *)data;
478 int len = 0, i = 0;
479
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200480 if (get_smart_data(drive, page, sub_cmd) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 unsigned short *val = (unsigned short *) page;
Bartlomiej Zolnierkiewicz151a6702008-10-10 22:39:28 +0200482 char *out = (char *)val + SECTOR_SIZE;
483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 page = out;
485 do {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200486 out += sprintf(out, "%04x%c", le16_to_cpu(*val),
487 (++i & 7) ? ' ' : '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 val += 1;
Bartlomiej Zolnierkiewicz151a6702008-10-10 22:39:28 +0200489 } while (i < SECTOR_SIZE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 len = out - page;
491 }
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200492
493 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200496static int proc_idedisk_read_sv
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 (char *page, char **start, off_t off, int count, int *eof, void *data)
498{
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200499 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200500 ATA_SMART_READ_VALUES);
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200501}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200503static int proc_idedisk_read_st
504 (char *page, char **start, off_t off, int count, int *eof, void *data)
505{
506 return proc_idedisk_read_smart(page, start, off, count, eof, data,
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200507 ATA_SMART_READ_THRESHOLDS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508}
509
510static ide_proc_entry_t idedisk_proc[] = {
Bartlomiej Zolnierkiewicz799ee572008-04-26 17:36:37 +0200511 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
512 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
513 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
514 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
515 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 { NULL, 0, NULL, NULL }
517};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200518#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Jens Axboe165125e2007-07-24 09:28:11 +0200520static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
522 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100523 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100525 /* FIXME: map struct ide_taskfile on rq->cmd[] */
526 BUG_ON(task == NULL);
527
528 memset(task, 0, sizeof(*task));
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200529 if (ata_id_flush_ext_enabled(drive->id) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200531 task->tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200533 task->tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100534 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
535 IDE_TFLAG_DYN;
536 task->data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100538 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200539 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz395d8ef2008-02-11 00:32:14 +0100540 rq->special = task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541}
542
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200543ide_devset_get(multcount, mult_count);
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545/*
546 * This is tightly woven into the driver->do_special can not touch.
547 * DON'T do it again until a total personality rewrite is committed.
548 */
549static int set_multcount(ide_drive_t *drive, int arg)
550{
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200551 struct request *rq;
552 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200554 if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200555 return -EINVAL;
556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 if (drive->special.b.set_multmode)
558 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100559
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200560 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
561 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 drive->mult_req = arg;
564 drive->special.b.set_multmode = 1;
FUJITA Tomonoridd470872008-07-15 21:21:43 +0200565 error = blk_execute_rq(drive->queue, NULL, rq, 0);
566 blk_put_request(rq);
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 return (drive->mult_count == arg) ? 0 : -EIO;
569}
570
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200571ide_devset_get(nowerr, nowerr);
572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573static int set_nowerr(ide_drive_t *drive, int arg)
574{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200575 if (arg < 0 || arg > 1)
576 return -EINVAL;
577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 if (ide_spin_wait_hwgroup(drive))
579 return -EBUSY;
580 drive->nowerr = arg;
581 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
582 spin_unlock_irq(&ide_lock);
583 return 0;
584}
585
Tejun Heo3e087b52006-01-06 09:57:31 +0100586static void update_ordered(ide_drive_t *drive)
587{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200588 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100589 unsigned ordered = QUEUE_ORDERED_NONE;
590 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100591
592 if (drive->wcache) {
593 unsigned long long capacity;
594 int barrier;
595 /*
596 * We must avoid issuing commands a drive does not
597 * understand or we may crash it. We check flush cache
598 * is supported. We also check we have the LBA48 flush
599 * cache if the drive capacity is too large. By this
600 * time we have trimmed the drive capacity if LBA48 is
601 * not available so we don't need to recheck that.
602 */
603 capacity = idedisk_capacity(drive);
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200604 barrier = ata_id_flush_enabled(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100605 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200606 ata_id_flush_ext_enabled(id));
Tejun Heo3e087b52006-01-06 09:57:31 +0100607
608 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800609 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100610
611 if (barrier) {
612 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
613 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100614 }
615 } else
616 ordered = QUEUE_ORDERED_DRAIN;
617
618 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100619}
620
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200621ide_devset_get(wcache, wcache);
622
623static int set_wcache(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
625 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100626 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200628 if (arg < 0 || arg > 1)
629 return -EINVAL;
630
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200631 if (ata_id_flush_enabled(drive->id)) {
Tejun Heo3e087b52006-01-06 09:57:31 +0100632 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100633 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200634 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
635 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100636 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100637 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100638 if (err == 0)
639 drive->wcache = arg;
640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Tejun Heo3e087b52006-01-06 09:57:31 +0100642 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Tejun Heo3e087b52006-01-06 09:57:31 +0100644 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645}
646
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200647static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
649 ide_task_t args;
650
651 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200652 if (ata_id_flush_ext_enabled(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200653 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200655 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100656 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100657 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658}
659
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200660ide_devset_get(acoustic, acoustic);
661
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200662static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
664 ide_task_t args;
665
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200666 if (arg < 0 || arg > 254)
667 return -EINVAL;
668
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200670 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100671 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200672 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100673 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100674 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 drive->acoustic = arg;
676 return 0;
677}
678
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200679ide_devset_get(lba_addressing, addressing);
680
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681/*
682 * drive->addressing:
683 * 0: 28-bit
684 * 1: 48-bit
685 * 2: 48-bit capable doing 28-bit
686 */
687static int set_lba_addressing(ide_drive_t *drive, int arg)
688{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200689 if (arg < 0 || arg > 2)
690 return -EINVAL;
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 drive->addressing = 0;
693
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200694 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 return 0;
696
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200697 if (ata_id_lba48_enabled(drive->id) == 0)
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200698 return -EIO;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 drive->addressing = arg;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 return 0;
703}
704
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200705#ifdef CONFIG_IDE_PROC_FS
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200706ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
707ide_devset_rw_nolock(address, 0, 2, lba_addressing);
708ide_devset_rw_nolock(multcount, 0, 16, multcount);
709ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
710ide_devset_rw_nolock(wcache, 0, 1, wcache);
711
712ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
713ide_devset_rw(bios_head, 0, 255, bios_head);
714ide_devset_rw(bios_sect, 0, 63, bios_sect);
715ide_devset_rw(failures, 0, 65535, failures);
716ide_devset_rw(lun, 0, 7, lun);
717ide_devset_rw(max_failures, 0, 65535, max_failures);
718
719static const struct ide_devset *idedisk_settings[] = {
720 &ide_devset_acoustic,
721 &ide_devset_address,
722 &ide_devset_bios_cyl,
723 &ide_devset_bios_head,
724 &ide_devset_bios_sect,
725 &ide_devset_failures,
726 &ide_devset_lun,
727 &ide_devset_max_failures,
728 &ide_devset_multcount,
729 &ide_devset_nowerr,
730 &ide_devset_wcache,
731 NULL
732};
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200733#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200735static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200737 struct ide_disk_obj *idkp = drive->driver_data;
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200738 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200739 u16 *id = drive->id;
740 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200743 ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 if (drive->id_read == 0)
746 return;
747
Richard Purdie98109332006-02-03 03:04:55 -0800748 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200750 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200752 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 }
755
756 (void)set_lba_addressing(drive, 1);
757
758 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 int max_s = 2048;
760
761 if (max_s > hwif->rqsize)
762 max_s = hwif->rqsize;
763
764 blk_queue_max_sectors(drive->queue, max_s);
765 }
766
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200767 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
768 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200771 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
773 /* limit drive capacity to 137GB if LBA48 cannot be used */
774 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
775 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
776 "%llu sectors (%llu MB)\n",
777 drive->name, (unsigned long long)drive->capacity64,
778 sectors_to_MB(drive->capacity64));
779 drive->capacity64 = 1ULL << 28;
780 }
781
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200782 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200784 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
785 " will be used for accessing sectors "
786 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 } else
788 drive->addressing = 0;
789 }
790
791 /*
792 * if possible, give fdisk access to more of the drive,
793 * by correcting bios_cyls:
794 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200795 capacity = idedisk_capacity(drive);
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 if (!drive->forced_geom) {
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200798 if (ata_id_lba48_enabled(drive->id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 /* compatibility */
800 drive->bios_sect = 63;
801 drive->bios_head = 255;
802 }
803
804 if (drive->bios_sect && drive->bios_head) {
805 unsigned int cap0 = capacity; /* truncate to 32 bits */
806 unsigned int cylsz, cyl;
807
808 if (cap0 != capacity)
809 drive->bios_cyl = 65535;
810 else {
811 cylsz = drive->bios_sect * drive->bios_head;
812 cyl = cap0 / cylsz;
813 if (cyl > 65535)
814 cyl = 65535;
815 if (cyl > drive->bios_cyl)
816 drive->bios_cyl = cyl;
817 }
818 }
819 }
820 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
821 drive->name, capacity, sectors_to_MB(capacity));
822
823 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200824 if (id[ATA_ID_BUF_SIZE])
825 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100827 printk(KERN_CONT ", CHS=%d/%d/%d\n",
828 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200831 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 drive->wcache = 1;
833
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200834 set_wcache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835}
836
837static void ide_cacheflush_p(ide_drive_t *drive)
838{
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200839 if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 return;
841
842 if (do_idedisk_flushcache(drive))
843 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
844}
845
Russell King4031bbe2006-01-06 11:41:00 +0000846static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
848 struct ide_disk_obj *idkp = drive->driver_data;
849 struct gendisk *g = idkp->disk;
850
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200851 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 del_gendisk(g);
854
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100855 ide_cacheflush_p(drive);
856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858}
859
860static void ide_disk_release(struct kref *kref)
861{
862 struct ide_disk_obj *idkp = to_ide_disk(kref);
863 ide_drive_t *drive = idkp->drive;
864 struct gendisk *g = idkp->disk;
865
866 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 g->private_data = NULL;
868 put_disk(g);
869 kfree(idkp);
870}
871
Russell King4031bbe2006-01-06 11:41:00 +0000872static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Lee Trager0d2157f2007-06-08 15:14:30 +0200874/*
875 * On HPA drives the capacity needs to be
876 * reinitilized on resume otherwise the disk
877 * can not be used and a hard reset is required
878 */
879static void ide_disk_resume(ide_drive_t *drive)
880{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200881 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200882 init_idedisk_capacity(drive);
883}
884
Russell King4031bbe2006-01-06 11:41:00 +0000885static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887#ifdef CONFIG_ALPHA
888 /* On Alpha, halt(8) doesn't actually turn the machine off,
889 it puts you into the sort of firmware monitor. Typically,
890 it's used to boot another kernel image, so it's not much
891 different from reboot(8). Therefore, we don't need to
892 spin down the disk in this case, especially since Alpha
893 firmware doesn't handle disks in standby mode properly.
894 On the other hand, it's reasonably safe to turn the power
895 off when the shutdown process reaches the firmware prompt,
896 as the firmware initialization takes rather long time -
897 at least 10 seconds, which should be sufficient for
898 the disk to expire its write cache. */
899 if (system_state != SYSTEM_POWER_OFF) {
900#else
901 if (system_state == SYSTEM_RESTART) {
902#endif
903 ide_cacheflush_p(drive);
904 return;
905 }
906
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100907 printk(KERN_INFO "Shutdown: %s\n", drive->name);
908
Russell King4031bbe2006-01-06 11:41:00 +0000909 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910}
911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100914 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200915 .name = "ide-disk",
916 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 },
Russell King4031bbe2006-01-06 11:41:00 +0000918 .probe = ide_disk_probe,
919 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200920 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000921 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 .version = IDEDISK_VERSION,
923 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 .do_request = ide_do_rw_disk,
925 .end_request = ide_end_request,
926 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200927#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200929 .settings = idedisk_settings,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200930#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931};
932
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100933static int idedisk_set_doorlock(ide_drive_t *drive, int on)
934{
935 ide_task_t task;
936
937 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200938 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100939 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100940
941 return ide_no_data_taskfile(drive, &task);
942}
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944static int idedisk_open(struct inode *inode, struct file *filp)
945{
946 struct gendisk *disk = inode->i_bdev->bd_disk;
947 struct ide_disk_obj *idkp;
948 ide_drive_t *drive;
949
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200950 idkp = ide_disk_get(disk);
951 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 return -ENXIO;
953
954 drive = idkp->drive;
955
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100956 idkp->openers++;
957
958 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 check_disk_change(inode->i_bdev);
960 /*
961 * Ignore the return code from door_lock,
962 * since the open() has already succeeded,
963 * and the door_lock is irrelevant at this point.
964 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100965 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 drive->doorlocking = 0;
967 }
968 return 0;
969}
970
971static int idedisk_release(struct inode *inode, struct file *filp)
972{
973 struct gendisk *disk = inode->i_bdev->bd_disk;
974 struct ide_disk_obj *idkp = ide_disk_g(disk);
975 ide_drive_t *drive = idkp->drive;
976
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100977 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100979
980 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100981 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 drive->doorlocking = 0;
983 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100984
985 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
987 ide_disk_put(idkp);
988
989 return 0;
990}
991
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800992static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
993{
994 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
995 ide_drive_t *drive = idkp->drive;
996
997 geo->heads = drive->bios_head;
998 geo->sectors = drive->bios_sect;
999 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1000 return 0;
1001}
1002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003static int idedisk_ioctl(struct inode *inode, struct file *file,
1004 unsigned int cmd, unsigned long arg)
1005{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001006 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 struct block_device *bdev = inode->i_bdev;
1008 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001009 ide_drive_t *drive = idkp->drive;
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001010 int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001011
1012 switch (cmd) {
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001013 case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
1014 case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
1015 case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
1016 case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
1017 case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001018 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1019 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1020 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001021 case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001022 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1023 }
1024
1025 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1026
1027read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001028 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001029 spin_lock_irqsave(&ide_lock, flags);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +02001030 err = getfunc(drive);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001031 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001032 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001033 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1034
1035set_val:
1036 if (bdev != bdev->bd_contains)
1037 err = -EINVAL;
1038 else {
1039 if (!capable(CAP_SYS_ADMIN))
1040 err = -EACCES;
1041 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001042 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001043 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001044 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001045 }
1046 }
1047 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048}
1049
1050static int idedisk_media_changed(struct gendisk *disk)
1051{
1052 struct ide_disk_obj *idkp = ide_disk_g(disk);
1053 ide_drive_t *drive = idkp->drive;
1054
1055 /* do not scan partitions twice if this is a removable device */
1056 if (drive->attach) {
1057 drive->attach = 0;
1058 return 0;
1059 }
1060 /* if removable, always assume it was changed */
1061 return drive->removable;
1062}
1063
1064static int idedisk_revalidate_disk(struct gendisk *disk)
1065{
1066 struct ide_disk_obj *idkp = ide_disk_g(disk);
1067 set_capacity(disk, idedisk_capacity(idkp->drive));
1068 return 0;
1069}
1070
1071static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001072 .owner = THIS_MODULE,
1073 .open = idedisk_open,
1074 .release = idedisk_release,
1075 .ioctl = idedisk_ioctl,
1076 .getgeo = idedisk_getgeo,
1077 .media_changed = idedisk_media_changed,
1078 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079};
1080
1081MODULE_DESCRIPTION("ATA DISK Driver");
1082
Russell King4031bbe2006-01-06 11:41:00 +00001083static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084{
1085 struct ide_disk_obj *idkp;
1086 struct gendisk *g;
1087
1088 /* strstr("foo", "") is non-NULL */
1089 if (!strstr("ide-disk", drive->driver_req))
1090 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 if (drive->media != ide_disk)
1093 goto failed;
1094
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001095 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 if (!idkp)
1097 goto failed;
1098
Tejun Heo689d6fa2008-08-25 19:56:16 +09001099 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 if (!g)
1101 goto out_free_idkp;
1102
1103 ide_init_disk(g, drive);
1104
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 kref_init(&idkp->kref);
1106
1107 idkp->drive = drive;
1108 idkp->driver = &idedisk_driver;
1109 idkp->disk = g;
1110
1111 g->private_data = &idkp->driver;
1112
1113 drive->driver_data = idkp;
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 idedisk_setup(drive);
1116 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1117 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1118 drive->name, drive->head);
1119 drive->attach = 0;
1120 } else
1121 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001122
Tejun Heof615b482008-08-25 19:47:24 +09001123 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001125 g->flags |= GENHD_FL_EXT_DEVT;
1126 if (drive->removable)
1127 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 set_capacity(g, idedisk_capacity(drive));
1129 g->fops = &idedisk_ops;
1130 add_disk(g);
1131 return 0;
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133out_free_idkp:
1134 kfree(idkp);
1135failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001136 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137}
1138
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001139static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001141 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142}
1143
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001144static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001146 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147}
1148
Kay Sievers263756e2005-12-12 18:03:44 +01001149MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150module_init(idedisk_init);
1151module_exit(idedisk_exit);
1152MODULE_LICENSE("GPL");