blob: 7ea075299bd9b59aa4feeedce7ebaaf20b65569e [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 Zolnierkiewicza02227c2008-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 drive->nowerr = arg;
579 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 return 0;
581}
582
Bartlomiej Zolnierkiewiczbe3c0962008-10-13 21:39:36 +0200583static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
584{
585 ide_task_t task;
586
587 memset(&task, 0, sizeof(task));
588 task.tf.feature = feature;
589 task.tf.nsect = nsect;
590 task.tf.command = ATA_CMD_SET_FEATURES;
591 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
592
593 return ide_no_data_taskfile(drive, &task);
594}
595
Tejun Heo3e087b52006-01-06 09:57:31 +0100596static void update_ordered(ide_drive_t *drive)
597{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200598 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100599 unsigned ordered = QUEUE_ORDERED_NONE;
600 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100601
602 if (drive->wcache) {
603 unsigned long long capacity;
604 int barrier;
605 /*
606 * We must avoid issuing commands a drive does not
607 * understand or we may crash it. We check flush cache
608 * is supported. We also check we have the LBA48 flush
609 * cache if the drive capacity is too large. By this
610 * time we have trimmed the drive capacity if LBA48 is
611 * not available so we don't need to recheck that.
612 */
613 capacity = idedisk_capacity(drive);
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200614 barrier = ata_id_flush_enabled(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100615 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200616 ata_id_flush_ext_enabled(id));
Tejun Heo3e087b52006-01-06 09:57:31 +0100617
618 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800619 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100620
621 if (barrier) {
622 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
623 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100624 }
625 } else
626 ordered = QUEUE_ORDERED_DRAIN;
627
628 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100629}
630
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200631ide_devset_get(wcache, wcache);
632
633static int set_wcache(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
Tejun Heo3e087b52006-01-06 09:57:31 +0100635 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200637 if (arg < 0 || arg > 1)
638 return -EINVAL;
639
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200640 if (ata_id_flush_enabled(drive->id)) {
Bartlomiej Zolnierkiewiczbe3c0962008-10-13 21:39:36 +0200641 err = ide_do_setfeature(drive,
642 arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
Tejun Heo3e087b52006-01-06 09:57:31 +0100643 if (err == 0)
644 drive->wcache = arg;
645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Tejun Heo3e087b52006-01-06 09:57:31 +0100647 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Tejun Heo3e087b52006-01-06 09:57:31 +0100649 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650}
651
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200652static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
654 ide_task_t args;
655
656 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200657 if (ata_id_flush_ext_enabled(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200658 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200660 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100661 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100662 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663}
664
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200665ide_devset_get(acoustic, acoustic);
666
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200667static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200669 if (arg < 0 || arg > 254)
670 return -EINVAL;
671
Bartlomiej Zolnierkiewiczbe3c0962008-10-13 21:39:36 +0200672 ide_do_setfeature(drive,
673 arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 drive->acoustic = arg;
Bartlomiej Zolnierkiewiczbe3c0962008-10-13 21:39:36 +0200676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 return 0;
678}
679
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200680ide_devset_get(addressing, addressing);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200681
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682/*
683 * drive->addressing:
684 * 0: 28-bit
685 * 1: 48-bit
686 * 2: 48-bit capable doing 28-bit
687 */
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200688static int set_addressing(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200690 if (arg < 0 || arg > 2)
691 return -EINVAL;
692
Bartlomiej Zolnierkiewicz35c13752008-10-13 21:39:36 +0200693 if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
694 ata_id_lba48_enabled(drive->id) == 0))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200695 return -EIO;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200696
Bartlomiej Zolnierkiewicz35c13752008-10-13 21:39:36 +0200697 if (arg == 2)
698 arg = 0;
699
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
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200705ide_devset_rw(acoustic, acoustic);
706ide_devset_rw(address, addressing);
707ide_devset_rw(multcount, multcount);
708ide_devset_rw(wcache, wcache);
709
710ide_devset_rw_sync(nowerr, nowerr);
711
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200712#ifdef CONFIG_IDE_PROC_FS
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200713ide_devset_rw_field(bios_cyl, bios_cyl);
714ide_devset_rw_field(bios_head, bios_head);
715ide_devset_rw_field(bios_sect, bios_sect);
716ide_devset_rw_field(failures, failures);
717ide_devset_rw_field(lun, lun);
718ide_devset_rw_field(max_failures, max_failures);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200719
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200720static const struct ide_proc_devset idedisk_settings[] = {
721 IDE_PROC_DEVSET(acoustic, 0, 254),
722 IDE_PROC_DEVSET(address, 0, 2),
723 IDE_PROC_DEVSET(bios_cyl, 0, 65535),
724 IDE_PROC_DEVSET(bios_head, 0, 255),
725 IDE_PROC_DEVSET(bios_sect, 0, 63),
726 IDE_PROC_DEVSET(failures, 0, 65535),
727 IDE_PROC_DEVSET(lun, 0, 7),
728 IDE_PROC_DEVSET(max_failures, 0, 65535),
729 IDE_PROC_DEVSET(multcount, 0, 16),
730 IDE_PROC_DEVSET(nowerr, 0, 1),
731 IDE_PROC_DEVSET(wcache, 0, 1),
732 { 0 },
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200733};
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200734#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200736static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737{
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200738 struct ide_disk_obj *idkp = drive->driver_data;
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200739 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200740 u16 *id = drive->id;
741 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200744 ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
746 if (drive->id_read == 0)
747 return;
748
Richard Purdie98109332006-02-03 03:04:55 -0800749 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200751 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200753 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200757 (void)set_addressing(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
759 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 int max_s = 2048;
761
762 if (max_s > hwif->rqsize)
763 max_s = hwif->rqsize;
764
765 blk_queue_max_sectors(drive->queue, max_s);
766 }
767
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200768 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
769 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
771 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200772 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 /* limit drive capacity to 137GB if LBA48 cannot be used */
775 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
776 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
777 "%llu sectors (%llu MB)\n",
778 drive->name, (unsigned long long)drive->capacity64,
779 sectors_to_MB(drive->capacity64));
780 drive->capacity64 = 1ULL << 28;
781 }
782
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200783 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200785 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
786 " will be used for accessing sectors "
787 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 } else
789 drive->addressing = 0;
790 }
791
792 /*
793 * if possible, give fdisk access to more of the drive,
794 * by correcting bios_cyls:
795 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200796 capacity = idedisk_capacity(drive);
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 if (!drive->forced_geom) {
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200799 if (ata_id_lba48_enabled(drive->id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 /* compatibility */
801 drive->bios_sect = 63;
802 drive->bios_head = 255;
803 }
804
805 if (drive->bios_sect && drive->bios_head) {
806 unsigned int cap0 = capacity; /* truncate to 32 bits */
807 unsigned int cylsz, cyl;
808
809 if (cap0 != capacity)
810 drive->bios_cyl = 65535;
811 else {
812 cylsz = drive->bios_sect * drive->bios_head;
813 cyl = cap0 / cylsz;
814 if (cyl > 65535)
815 cyl = 65535;
816 if (cyl > drive->bios_cyl)
817 drive->bios_cyl = cyl;
818 }
819 }
820 }
821 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
822 drive->name, capacity, sectors_to_MB(capacity));
823
824 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200825 if (id[ATA_ID_BUF_SIZE])
826 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100828 printk(KERN_CONT ", CHS=%d/%d/%d\n",
829 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200832 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 drive->wcache = 1;
834
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200835 set_wcache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836}
837
838static void ide_cacheflush_p(ide_drive_t *drive)
839{
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200840 if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 return;
842
843 if (do_idedisk_flushcache(drive))
844 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
845}
846
Russell King4031bbe2006-01-06 11:41:00 +0000847static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 struct ide_disk_obj *idkp = drive->driver_data;
850 struct gendisk *g = idkp->disk;
851
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200852 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 del_gendisk(g);
855
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100856 ide_cacheflush_p(drive);
857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859}
860
861static void ide_disk_release(struct kref *kref)
862{
863 struct ide_disk_obj *idkp = to_ide_disk(kref);
864 ide_drive_t *drive = idkp->drive;
865 struct gendisk *g = idkp->disk;
866
867 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 g->private_data = NULL;
869 put_disk(g);
870 kfree(idkp);
871}
872
Russell King4031bbe2006-01-06 11:41:00 +0000873static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
Lee Trager0d2157f2007-06-08 15:14:30 +0200875/*
876 * On HPA drives the capacity needs to be
877 * reinitilized on resume otherwise the disk
878 * can not be used and a hard reset is required
879 */
880static void ide_disk_resume(ide_drive_t *drive)
881{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200882 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200883 init_idedisk_capacity(drive);
884}
885
Russell King4031bbe2006-01-06 11:41:00 +0000886static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888#ifdef CONFIG_ALPHA
889 /* On Alpha, halt(8) doesn't actually turn the machine off,
890 it puts you into the sort of firmware monitor. Typically,
891 it's used to boot another kernel image, so it's not much
892 different from reboot(8). Therefore, we don't need to
893 spin down the disk in this case, especially since Alpha
894 firmware doesn't handle disks in standby mode properly.
895 On the other hand, it's reasonably safe to turn the power
896 off when the shutdown process reaches the firmware prompt,
897 as the firmware initialization takes rather long time -
898 at least 10 seconds, which should be sufficient for
899 the disk to expire its write cache. */
900 if (system_state != SYSTEM_POWER_OFF) {
901#else
902 if (system_state == SYSTEM_RESTART) {
903#endif
904 ide_cacheflush_p(drive);
905 return;
906 }
907
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100908 printk(KERN_INFO "Shutdown: %s\n", drive->name);
909
Russell King4031bbe2006-01-06 11:41:00 +0000910 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911}
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100915 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200916 .name = "ide-disk",
917 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 },
Russell King4031bbe2006-01-06 11:41:00 +0000919 .probe = ide_disk_probe,
920 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200921 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000922 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 .version = IDEDISK_VERSION,
924 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 .do_request = ide_do_rw_disk,
926 .end_request = ide_end_request,
927 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200928#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200930 .settings = idedisk_settings,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200931#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932};
933
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100934static int idedisk_set_doorlock(ide_drive_t *drive, int on)
935{
936 ide_task_t task;
937
938 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200939 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100940 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100941
942 return ide_no_data_taskfile(drive, &task);
943}
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945static int idedisk_open(struct inode *inode, struct file *filp)
946{
947 struct gendisk *disk = inode->i_bdev->bd_disk;
948 struct ide_disk_obj *idkp;
949 ide_drive_t *drive;
950
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200951 idkp = ide_disk_get(disk);
952 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return -ENXIO;
954
955 drive = idkp->drive;
956
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100957 idkp->openers++;
958
959 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 check_disk_change(inode->i_bdev);
961 /*
962 * Ignore the return code from door_lock,
963 * since the open() has already succeeded,
964 * and the door_lock is irrelevant at this point.
965 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100966 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 drive->doorlocking = 0;
968 }
969 return 0;
970}
971
972static int idedisk_release(struct inode *inode, struct file *filp)
973{
974 struct gendisk *disk = inode->i_bdev->bd_disk;
975 struct ide_disk_obj *idkp = ide_disk_g(disk);
976 ide_drive_t *drive = idkp->drive;
977
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100978 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100980
981 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100982 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 drive->doorlocking = 0;
984 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100985
986 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988 ide_disk_put(idkp);
989
990 return 0;
991}
992
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800993static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
994{
995 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
996 ide_drive_t *drive = idkp->drive;
997
998 geo->heads = drive->bios_head;
999 geo->sectors = drive->bios_sect;
1000 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1001 return 0;
1002}
1003
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001004static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +02001005{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
1006{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
1007{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
1008{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
1009{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001010{ 0 }
1011};
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013static int idedisk_ioctl(struct inode *inode, struct file *file,
1014 unsigned int cmd, unsigned long arg)
1015{
1016 struct block_device *bdev = inode->i_bdev;
1017 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001018 ide_drive_t *drive = idkp->drive;
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001019 int err;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001020
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001021 err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
1022 if (err != -EOPNOTSUPP)
1023 return err;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001024
1025 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026}
1027
1028static int idedisk_media_changed(struct gendisk *disk)
1029{
1030 struct ide_disk_obj *idkp = ide_disk_g(disk);
1031 ide_drive_t *drive = idkp->drive;
1032
1033 /* do not scan partitions twice if this is a removable device */
1034 if (drive->attach) {
1035 drive->attach = 0;
1036 return 0;
1037 }
1038 /* if removable, always assume it was changed */
1039 return drive->removable;
1040}
1041
1042static int idedisk_revalidate_disk(struct gendisk *disk)
1043{
1044 struct ide_disk_obj *idkp = ide_disk_g(disk);
1045 set_capacity(disk, idedisk_capacity(idkp->drive));
1046 return 0;
1047}
1048
1049static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001050 .owner = THIS_MODULE,
1051 .open = idedisk_open,
1052 .release = idedisk_release,
1053 .ioctl = idedisk_ioctl,
1054 .getgeo = idedisk_getgeo,
1055 .media_changed = idedisk_media_changed,
1056 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057};
1058
1059MODULE_DESCRIPTION("ATA DISK Driver");
1060
Russell King4031bbe2006-01-06 11:41:00 +00001061static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062{
1063 struct ide_disk_obj *idkp;
1064 struct gendisk *g;
1065
1066 /* strstr("foo", "") is non-NULL */
1067 if (!strstr("ide-disk", drive->driver_req))
1068 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 if (drive->media != ide_disk)
1071 goto failed;
1072
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001073 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 if (!idkp)
1075 goto failed;
1076
Tejun Heo689d6fa2008-08-25 19:56:16 +09001077 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 if (!g)
1079 goto out_free_idkp;
1080
1081 ide_init_disk(g, drive);
1082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 kref_init(&idkp->kref);
1084
1085 idkp->drive = drive;
1086 idkp->driver = &idedisk_driver;
1087 idkp->disk = g;
1088
1089 g->private_data = &idkp->driver;
1090
1091 drive->driver_data = idkp;
1092
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 idedisk_setup(drive);
1094 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1095 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1096 drive->name, drive->head);
1097 drive->attach = 0;
1098 } else
1099 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001100
Tejun Heof615b482008-08-25 19:47:24 +09001101 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001103 g->flags |= GENHD_FL_EXT_DEVT;
1104 if (drive->removable)
1105 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 set_capacity(g, idedisk_capacity(drive));
1107 g->fops = &idedisk_ops;
1108 add_disk(g);
1109 return 0;
1110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111out_free_idkp:
1112 kfree(idkp);
1113failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001114 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
1116
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001117static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001119 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120}
1121
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001122static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001124 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125}
1126
Kay Sievers263756e2005-12-12 18:03:44 +01001127MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128module_init(idedisk_init);
1129module_exit(idedisk_exit);
1130MODULE_LICENSE("GPL");