blob: 65c499aab6641b3c45ef1e4109cc89e7fc5bfb40 [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
Tejun Heo3e087b52006-01-06 09:57:31 +0100583static void update_ordered(ide_drive_t *drive)
584{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200585 u16 *id = drive->id;
Tejun Heo3e087b52006-01-06 09:57:31 +0100586 unsigned ordered = QUEUE_ORDERED_NONE;
587 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100588
589 if (drive->wcache) {
590 unsigned long long capacity;
591 int barrier;
592 /*
593 * We must avoid issuing commands a drive does not
594 * understand or we may crash it. We check flush cache
595 * is supported. We also check we have the LBA48 flush
596 * cache if the drive capacity is too large. By this
597 * time we have trimmed the drive capacity if LBA48 is
598 * not available so we don't need to recheck that.
599 */
600 capacity = idedisk_capacity(drive);
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200601 barrier = ata_id_flush_enabled(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100602 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200603 ata_id_flush_ext_enabled(id));
Tejun Heo3e087b52006-01-06 09:57:31 +0100604
605 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800606 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100607
608 if (barrier) {
609 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
610 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100611 }
612 } else
613 ordered = QUEUE_ORDERED_DRAIN;
614
615 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100616}
617
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200618ide_devset_get(wcache, wcache);
619
620static int set_wcache(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100623 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200625 if (arg < 0 || arg > 1)
626 return -EINVAL;
627
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200628 if (ata_id_flush_enabled(drive->id)) {
Tejun Heo3e087b52006-01-06 09:57:31 +0100629 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100630 args.tf.feature = arg ?
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200631 SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
632 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100633 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100634 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100635 if (err == 0)
636 drive->wcache = arg;
637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Tejun Heo3e087b52006-01-06 09:57:31 +0100639 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Tejun Heo3e087b52006-01-06 09:57:31 +0100641 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642}
643
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200644static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 ide_task_t args;
647
648 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczff2779b2008-10-10 22:39:31 +0200649 if (ata_id_flush_ext_enabled(drive->id))
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200650 args.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 else
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200652 args.tf.command = ATA_CMD_FLUSH;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100653 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100654 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655}
656
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200657ide_devset_get(acoustic, acoustic);
658
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200659static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
661 ide_task_t args;
662
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200663 if (arg < 0 || arg > 254)
664 return -EINVAL;
665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200667 args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100668 args.tf.nsect = arg;
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200669 args.tf.command = ATA_CMD_SET_FEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100670 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100671 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 drive->acoustic = arg;
673 return 0;
674}
675
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200676ide_devset_get(addressing, addressing);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678/*
679 * drive->addressing:
680 * 0: 28-bit
681 * 1: 48-bit
682 * 2: 48-bit capable doing 28-bit
683 */
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200684static int set_addressing(ide_drive_t *drive, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200686 if (arg < 0 || arg > 2)
687 return -EINVAL;
688
Bartlomiej Zolnierkiewicz35c13752008-10-13 21:39:36 +0200689 if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
690 ata_id_lba48_enabled(drive->id) == 0))
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200691 return -EIO;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200692
Bartlomiej Zolnierkiewicz35c13752008-10-13 21:39:36 +0200693 if (arg == 2)
694 arg = 0;
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 drive->addressing = arg;
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 return 0;
699}
700
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200701ide_devset_rw(acoustic, acoustic);
702ide_devset_rw(address, addressing);
703ide_devset_rw(multcount, multcount);
704ide_devset_rw(wcache, wcache);
705
706ide_devset_rw_sync(nowerr, nowerr);
707
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200708#ifdef CONFIG_IDE_PROC_FS
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200709ide_devset_rw_field(bios_cyl, bios_cyl);
710ide_devset_rw_field(bios_head, bios_head);
711ide_devset_rw_field(bios_sect, bios_sect);
712ide_devset_rw_field(failures, failures);
713ide_devset_rw_field(lun, lun);
714ide_devset_rw_field(max_failures, max_failures);
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200715
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +0200716static const struct ide_proc_devset idedisk_settings[] = {
717 IDE_PROC_DEVSET(acoustic, 0, 254),
718 IDE_PROC_DEVSET(address, 0, 2),
719 IDE_PROC_DEVSET(bios_cyl, 0, 65535),
720 IDE_PROC_DEVSET(bios_head, 0, 255),
721 IDE_PROC_DEVSET(bios_sect, 0, 63),
722 IDE_PROC_DEVSET(failures, 0, 65535),
723 IDE_PROC_DEVSET(lun, 0, 7),
724 IDE_PROC_DEVSET(max_failures, 0, 65535),
725 IDE_PROC_DEVSET(multcount, 0, 16),
726 IDE_PROC_DEVSET(nowerr, 0, 1),
727 IDE_PROC_DEVSET(wcache, 0, 1),
728 { 0 },
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200729};
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200730#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200732static void idedisk_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200734 struct ide_disk_obj *idkp = drive->driver_data;
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200735 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200736 u16 *id = drive->id;
737 char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
Bartlomiej Zolnierkiewicz1e874f42008-10-10 22:39:27 +0200740 ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
742 if (drive->id_read == 0)
743 return;
744
Richard Purdie98109332006-02-03 03:04:55 -0800745 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 /*
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200747 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200749 if (m[0] != 'W' || m[1] != 'D')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 drive->doorlocking = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 }
752
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +0200753 (void)set_addressing(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 int max_s = 2048;
757
758 if (max_s > hwif->rqsize)
759 max_s = hwif->rqsize;
760
761 blk_queue_max_sectors(drive->queue, max_s);
762 }
763
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200764 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
765 drive->queue->max_sectors / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
767 /* calculate drive capacity, and select LBA if possible */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200768 init_idedisk_capacity(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 /* limit drive capacity to 137GB if LBA48 cannot be used */
771 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
772 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
773 "%llu sectors (%llu MB)\n",
774 drive->name, (unsigned long long)drive->capacity64,
775 sectors_to_MB(drive->capacity64));
776 drive->capacity64 = 1ULL << 28;
777 }
778
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200779 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (drive->capacity64 > 1ULL << 28) {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200781 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
782 " will be used for accessing sectors "
783 "> %u\n", drive->name, 1 << 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 } else
785 drive->addressing = 0;
786 }
787
788 /*
789 * if possible, give fdisk access to more of the drive,
790 * by correcting bios_cyls:
791 */
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200792 capacity = idedisk_capacity(drive);
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (!drive->forced_geom) {
Bartlomiej Zolnierkiewicz942dcd82008-10-10 22:39:30 +0200795 if (ata_id_lba48_enabled(drive->id)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 /* compatibility */
797 drive->bios_sect = 63;
798 drive->bios_head = 255;
799 }
800
801 if (drive->bios_sect && drive->bios_head) {
802 unsigned int cap0 = capacity; /* truncate to 32 bits */
803 unsigned int cylsz, cyl;
804
805 if (cap0 != capacity)
806 drive->bios_cyl = 65535;
807 else {
808 cylsz = drive->bios_sect * drive->bios_head;
809 cyl = cap0 / cylsz;
810 if (cyl > 65535)
811 cyl = 65535;
812 if (cyl > drive->bios_cyl)
813 drive->bios_cyl = cyl;
814 }
815 }
816 }
817 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
818 drive->name, capacity, sectors_to_MB(capacity));
819
820 /* Only print cache size when it was specified */
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200821 if (id[ATA_ID_BUF_SIZE])
822 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100824 printk(KERN_CONT ", CHS=%d/%d/%d\n",
825 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* write cache enabled? */
Bartlomiej Zolnierkiewicz8a089c62008-10-10 22:39:20 +0200828 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 drive->wcache = 1;
830
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200831 set_wcache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832}
833
834static void ide_cacheflush_p(ide_drive_t *drive)
835{
Bartlomiej Zolnierkiewicz4b58f172008-10-10 22:39:30 +0200836 if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return;
838
839 if (do_idedisk_flushcache(drive))
840 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
841}
842
Russell King4031bbe2006-01-06 11:41:00 +0000843static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 struct ide_disk_obj *idkp = drive->driver_data;
846 struct gendisk *g = idkp->disk;
847
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200848 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 del_gendisk(g);
851
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100852 ide_cacheflush_p(drive);
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855}
856
857static void ide_disk_release(struct kref *kref)
858{
859 struct ide_disk_obj *idkp = to_ide_disk(kref);
860 ide_drive_t *drive = idkp->drive;
861 struct gendisk *g = idkp->disk;
862
863 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 g->private_data = NULL;
865 put_disk(g);
866 kfree(idkp);
867}
868
Russell King4031bbe2006-01-06 11:41:00 +0000869static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Lee Trager0d2157f2007-06-08 15:14:30 +0200871/*
872 * On HPA drives the capacity needs to be
873 * reinitilized on resume otherwise the disk
874 * can not be used and a hard reset is required
875 */
876static void ide_disk_resume(ide_drive_t *drive)
877{
Bartlomiej Zolnierkiewiczf41891c2008-10-10 22:39:20 +0200878 if (ata_id_hpa_enabled(drive->id))
Lee Trager0d2157f2007-06-08 15:14:30 +0200879 init_idedisk_capacity(drive);
880}
881
Russell King4031bbe2006-01-06 11:41:00 +0000882static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884#ifdef CONFIG_ALPHA
885 /* On Alpha, halt(8) doesn't actually turn the machine off,
886 it puts you into the sort of firmware monitor. Typically,
887 it's used to boot another kernel image, so it's not much
888 different from reboot(8). Therefore, we don't need to
889 spin down the disk in this case, especially since Alpha
890 firmware doesn't handle disks in standby mode properly.
891 On the other hand, it's reasonably safe to turn the power
892 off when the shutdown process reaches the firmware prompt,
893 as the firmware initialization takes rather long time -
894 at least 10 seconds, which should be sufficient for
895 the disk to expire its write cache. */
896 if (system_state != SYSTEM_POWER_OFF) {
897#else
898 if (system_state == SYSTEM_RESTART) {
899#endif
900 ide_cacheflush_p(drive);
901 return;
902 }
903
Bartlomiej Zolnierkiewiczd12faa22008-02-26 21:50:36 +0100904 printk(KERN_INFO "Shutdown: %s\n", drive->name);
905
Russell King4031bbe2006-01-06 11:41:00 +0000906 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907}
908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100911 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200912 .name = "ide-disk",
913 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 },
Russell King4031bbe2006-01-06 11:41:00 +0000915 .probe = ide_disk_probe,
916 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200917 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000918 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 .version = IDEDISK_VERSION,
920 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 .do_request = ide_do_rw_disk,
922 .end_request = ide_end_request,
923 .error = __ide_error,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200924#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz8185d5a2008-10-10 22:39:28 +0200926 .settings = idedisk_settings,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200927#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928};
929
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100930static int idedisk_set_doorlock(ide_drive_t *drive, int on)
931{
932 ide_task_t task;
933
934 memset(&task, 0, sizeof(task));
Bartlomiej Zolnierkiewiczaaaade32008-10-10 22:39:21 +0200935 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100936 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100937
938 return ide_no_data_taskfile(drive, &task);
939}
940
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941static int idedisk_open(struct inode *inode, struct file *filp)
942{
943 struct gendisk *disk = inode->i_bdev->bd_disk;
944 struct ide_disk_obj *idkp;
945 ide_drive_t *drive;
946
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +0200947 idkp = ide_disk_get(disk);
948 if (idkp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return -ENXIO;
950
951 drive = idkp->drive;
952
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100953 idkp->openers++;
954
955 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 check_disk_change(inode->i_bdev);
957 /*
958 * Ignore the return code from door_lock,
959 * since the open() has already succeeded,
960 * and the door_lock is irrelevant at this point.
961 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100962 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 drive->doorlocking = 0;
964 }
965 return 0;
966}
967
968static int idedisk_release(struct inode *inode, struct file *filp)
969{
970 struct gendisk *disk = inode->i_bdev->bd_disk;
971 struct ide_disk_obj *idkp = ide_disk_g(disk);
972 ide_drive_t *drive = idkp->drive;
973
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100974 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100976
977 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100978 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 drive->doorlocking = 0;
980 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100981
982 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 ide_disk_put(idkp);
985
986 return 0;
987}
988
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800989static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
990{
991 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
992 ide_drive_t *drive = idkp->drive;
993
994 geo->heads = drive->bios_head;
995 geo->sectors = drive->bios_sect;
996 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
997 return 0;
998}
999
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001000static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
Elias Oltmanns92f1f8f2008-10-10 22:39:40 +02001001{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
1002{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
1003{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
1004{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
1005{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001006{ 0 }
1007};
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009static int idedisk_ioctl(struct inode *inode, struct file *file,
1010 unsigned int cmd, unsigned long arg)
1011{
1012 struct block_device *bdev = inode->i_bdev;
1013 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001014 ide_drive_t *drive = idkp->drive;
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001015 int err;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001016
Bartlomiej Zolnierkiewiczaa7687732008-10-10 22:39:33 +02001017 err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
1018 if (err != -EOPNOTSUPP)
1019 return err;
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001020
1021 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022}
1023
1024static int idedisk_media_changed(struct gendisk *disk)
1025{
1026 struct ide_disk_obj *idkp = ide_disk_g(disk);
1027 ide_drive_t *drive = idkp->drive;
1028
1029 /* do not scan partitions twice if this is a removable device */
1030 if (drive->attach) {
1031 drive->attach = 0;
1032 return 0;
1033 }
1034 /* if removable, always assume it was changed */
1035 return drive->removable;
1036}
1037
1038static int idedisk_revalidate_disk(struct gendisk *disk)
1039{
1040 struct ide_disk_obj *idkp = ide_disk_g(disk);
1041 set_capacity(disk, idedisk_capacity(idkp->drive));
1042 return 0;
1043}
1044
1045static struct block_device_operations idedisk_ops = {
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001046 .owner = THIS_MODULE,
1047 .open = idedisk_open,
1048 .release = idedisk_release,
1049 .ioctl = idedisk_ioctl,
1050 .getgeo = idedisk_getgeo,
1051 .media_changed = idedisk_media_changed,
1052 .revalidate_disk = idedisk_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053};
1054
1055MODULE_DESCRIPTION("ATA DISK Driver");
1056
Russell King4031bbe2006-01-06 11:41:00 +00001057static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058{
1059 struct ide_disk_obj *idkp;
1060 struct gendisk *g;
1061
1062 /* strstr("foo", "") is non-NULL */
1063 if (!strstr("ide-disk", drive->driver_req))
1064 goto failed;
Bartlomiej Zolnierkiewicz2a924662008-10-10 22:39:24 +02001065
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 if (drive->media != ide_disk)
1067 goto failed;
1068
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001069 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 if (!idkp)
1071 goto failed;
1072
Tejun Heo689d6fa2008-08-25 19:56:16 +09001073 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 if (!g)
1075 goto out_free_idkp;
1076
1077 ide_init_disk(g, drive);
1078
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 kref_init(&idkp->kref);
1080
1081 idkp->drive = drive;
1082 idkp->driver = &idedisk_driver;
1083 idkp->disk = g;
1084
1085 g->private_data = &idkp->driver;
1086
1087 drive->driver_data = idkp;
1088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 idedisk_setup(drive);
1090 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1091 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1092 drive->name, drive->head);
1093 drive->attach = 0;
1094 } else
1095 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001096
Tejun Heof615b482008-08-25 19:47:24 +09001097 g->minors = IDE_DISK_MINORS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 g->driverfs_dev = &drive->gendev;
Tejun Heo689d6fa2008-08-25 19:56:16 +09001099 g->flags |= GENHD_FL_EXT_DEVT;
1100 if (drive->removable)
1101 g->flags |= GENHD_FL_REMOVABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 set_capacity(g, idedisk_capacity(drive));
1103 g->fops = &idedisk_ops;
1104 add_disk(g);
1105 return 0;
1106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107out_free_idkp:
1108 kfree(idkp);
1109failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001110 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
Bartlomiej Zolnierkiewicz98416542008-04-26 17:36:37 +02001113static void __exit idedisk_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001115 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116}
1117
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001118static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001120 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121}
1122
Kay Sievers263756e2005-12-12 18:03:44 +01001123MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124module_init(idedisk_init);
1125module_exit(idedisk_exit);
1126MODULE_LICENSE("GPL");