blob: dc4a71b9f2873c57dfdbc625ae0a746b14e33a32 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * 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 */
7
8/*
9 * Mostly written by Mark Lord <mlord@pobox.com>
10 * and Gadi Oxman <gadio@netvision.net.il>
11 * and Andre Hedrick <andre@linux-ide.org>
12 *
13 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 */
15
16#define IDEDISK_VERSION "1.18"
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018//#define DEBUG
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/kernel.h>
24#include <linux/timer.h>
25#include <linux/mm.h>
26#include <linux/interrupt.h>
27#include <linux/major.h>
28#include <linux/errno.h>
29#include <linux/genhd.h>
30#include <linux/slab.h>
31#include <linux/delay.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080032#include <linux/mutex.h>
Richard Purdie2bfb6462006-03-31 02:31:16 -080033#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35#define _IDE_DISK
36
37#include <linux/ide.h>
38
39#include <asm/byteorder.h>
40#include <asm/irq.h>
41#include <asm/uaccess.h>
42#include <asm/io.h>
43#include <asm/div64.h>
44
45struct ide_disk_obj {
46 ide_drive_t *drive;
47 ide_driver_t *driver;
48 struct gendisk *disk;
49 struct kref kref;
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +010050 unsigned int openers; /* protected by BKL for now */
Linus Torvalds1da177e2005-04-16 15:20:36 -070051};
52
Arjan van de Vencf8b8972006-03-23 03:00:45 -080053static DEFINE_MUTEX(idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
56
57#define ide_disk_g(disk) \
58 container_of((disk)->private_data, struct ide_disk_obj, driver)
59
60static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
61{
62 struct ide_disk_obj *idkp = NULL;
63
Arjan van de Vencf8b8972006-03-23 03:00:45 -080064 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 idkp = ide_disk_g(disk);
66 if (idkp)
67 kref_get(&idkp->kref);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080068 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 return idkp;
70}
71
72static void ide_disk_release(struct kref *);
73
74static void ide_disk_put(struct ide_disk_obj *idkp)
75{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080076 mutex_lock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 kref_put(&idkp->kref, ide_disk_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080078 mutex_unlock(&idedisk_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079}
80
81/*
82 * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
83 * value for this drive (from its reported identification information).
84 *
85 * Returns: 1 if lba_capacity looks sensible
86 * 0 otherwise
87 *
88 * It is called only once for each drive.
89 */
90static int lba_capacity_is_ok (struct hd_driveid *id)
91{
92 unsigned long lba_sects, chs_sects, head, tail;
93
Alan Cox6efd9362005-06-27 15:24:22 -070094 /* No non-LBA info .. so valid! */
95 if (id->cyls == 0)
96 return 1;
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 /*
99 * The ATA spec tells large drives to return
100 * C/H/S = 16383/16/63 independent of their size.
101 * Some drives can be jumpered to use 15 heads instead of 16.
102 * Some drives can be jumpered to use 4092 cyls instead of 16383.
103 */
104 if ((id->cyls == 16383
105 || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
106 id->sectors == 63 &&
107 (id->heads == 15 || id->heads == 16) &&
108 (id->lba_capacity >= 16383*63*id->heads))
109 return 1;
110
111 lba_sects = id->lba_capacity;
112 chs_sects = id->cyls * id->heads * id->sectors;
113
114 /* perform a rough sanity check on lba_sects: within 10% is OK */
115 if ((lba_sects - chs_sects) < chs_sects/10)
116 return 1;
117
118 /* some drives have the word order reversed */
119 head = ((lba_sects >> 16) & 0xffff);
120 tail = (lba_sects & 0xffff);
121 lba_sects = (head | (tail << 16));
122 if ((lba_sects - chs_sects) < chs_sects/10) {
123 id->lba_capacity = lba_sects;
124 return 1; /* lba_capacity is (now) good */
125 }
126
127 return 0; /* lba_capacity value may be bad */
128}
129
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100130static const u8 ide_rw_cmds[] = {
131 WIN_MULTREAD,
132 WIN_MULTWRITE,
133 WIN_MULTREAD_EXT,
134 WIN_MULTWRITE_EXT,
135 WIN_READ,
136 WIN_WRITE,
137 WIN_READ_EXT,
138 WIN_WRITE_EXT,
139 WIN_READDMA,
140 WIN_WRITEDMA,
141 WIN_READDMA_EXT,
142 WIN_WRITEDMA_EXT,
143};
144
145static const u8 ide_data_phases[] = {
146 TASKFILE_MULTI_IN,
147 TASKFILE_MULTI_OUT,
148 TASKFILE_IN,
149 TASKFILE_OUT,
150 TASKFILE_IN_DMA,
151 TASKFILE_OUT_DMA,
152};
153
154static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
155{
156 u8 index, lba48, write;
157
158 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
159 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
160
161 if (dma)
162 index = drive->vdma ? 4 : 8;
163 else
164 index = drive->mult_count ? 0 : 4;
165
166 task->tf.command = ide_rw_cmds[index + lba48 + write];
167
168 if (dma)
169 index = 8; /* fixup index */
170
171 task->data_phase = ide_data_phases[index / 2 + write];
172}
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174/*
175 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
176 * using LBA if supported, or CHS otherwise, to address sectors.
177 */
178static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
179{
180 ide_hwif_t *hwif = HWIF(drive);
181 unsigned int dma = drive->using_dma;
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100182 u16 nsectors = (u16)rq->nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 u8 lba48 = (drive->addressing == 1) ? 1 : 0;
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100184 ide_task_t task;
185 struct ide_taskfile *tf = &task.tf;
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100186 ide_startstop_t rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200188 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 if (block + rq->nr_sectors > 1ULL << 28)
190 dma = 0;
191 else
192 lba48 = 0;
193 }
194
195 if (!dma) {
196 ide_init_sg_cmd(drive, rq);
197 ide_map_sg(drive, rq);
198 }
199
Bartlomiej Zolnierkiewicz9e422372008-01-25 22:17:07 +0100200 memset(&task, 0, sizeof(task));
201 task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100202 task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 if (drive->select.b.lba) {
205 if (lba48) {
Michael Richardsonc2f83112006-02-07 12:58:33 -0800206 pr_debug("%s: LBA=0x%012llx\n", drive->name,
207 (unsigned long long)block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100209 tf->hob_nsect = (nsectors >> 8) & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100210 tf->hob_lbal = (u8)(block >> 24);
211 if (sizeof(block) != 4) {
212 tf->hob_lbam = (u8)((u64)block >> 32);
213 tf->hob_lbah = (u8)((u64)block >> 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 }
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100215
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100216 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100217 tf->lbal = (u8) block;
218 tf->lbam = (u8)(block >> 8);
219 tf->lbah = (u8)(block >> 16);
Bartlomiej Zolnierkiewicz6dd9b832008-01-26 20:13:03 +0100220
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100221 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 } else {
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100223 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100224 tf->lbal = block;
225 tf->lbam = block >>= 8;
226 tf->lbah = block >>= 8;
227 tf->device = (block >> 8) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 }
229 } else {
230 unsigned int sect,head,cyl,track;
231 track = (int)block / drive->sect;
232 sect = (int)block % drive->sect + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 head = track % drive->head;
234 cyl = track / drive->head;
235
236 pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
237
Bartlomiej Zolnierkiewicz790d1232008-01-25 22:17:12 +0100238 tf->nsect = nsectors & 0xff;
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100239 tf->lbal = sect;
240 tf->lbam = cyl;
241 tf->lbah = cyl >> 8;
242 tf->device = head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
244
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100245 if (rq_data_dir(rq))
246 task.tf_flags |= IDE_TFLAG_WRITE;
247
248 ide_tf_set_cmd(drive, &task, dma);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100249 if (!dma)
250 hwif->data_phase = task.data_phase;
251 task.rq = rq;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100252
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100253 rc = do_rw_taskfile(drive, &task);
Bartlomiej Zolnierkiewicz2bd06b22008-01-25 22:17:06 +0100254
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100255 if (rc == ide_stopped && dma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 /* fallback to PIO */
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100257 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
Bartlomiej Zolnierkiewiczba76ae32008-01-25 22:17:16 +0100258 ide_tf_set_cmd(drive, &task, 0);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100259 hwif->data_phase = task.data_phase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 ide_init_sg_cmd(drive, rq);
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100261 rc = do_rw_taskfile(drive, &task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 }
263
Bartlomiej Zolnierkiewiczf6e29e32008-01-25 22:17:16 +0100264 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265}
266
267/*
268 * 268435455 == 137439 MB or 28bit limit
269 * 320173056 == 163929 MB or 48bit addressing
270 * 1073741822 == 549756 MB or 48bit addressing fake drive
271 */
272
273static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
274{
275 ide_hwif_t *hwif = HWIF(drive);
276
277 BUG_ON(drive->blocked);
278
279 if (!blk_fs_request(rq)) {
280 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
281 ide_end_request(drive, 0, 0);
282 return ide_stopped;
283 }
284
Richard Purdie2bfb6462006-03-31 02:31:16 -0800285 ledtrig_ide_activity();
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
288 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
Michael Richardsonc2f83112006-02-07 12:58:33 -0800289 (unsigned long long)block, rq->nr_sectors,
290 (unsigned long)rq->buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 if (hwif->rw_disk)
293 hwif->rw_disk(drive, rq);
294
295 return __ide_do_rw_disk(drive, rq, block);
296}
297
298/*
299 * Queries for true maximum capacity of the drive.
300 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
301 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100302static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
304 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100305 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100306 u64 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308 /* Create IDE/ATA command request structure */
309 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100310 if (lba48)
311 tf->command = WIN_READ_NATIVE_MAX_EXT;
312 else
313 tf->command = WIN_READ_NATIVE_MAX;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100314 tf->device = ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100315 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100316 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100317 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100319 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100322 if ((tf->status & 0x01) == 0)
323 addr = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 return addr;
326}
327
328/*
329 * Sets maximum virtual LBA address of the drive.
330 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
331 */
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100332static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333{
334 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100335 struct ide_taskfile *tf = &args.tf;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100336 u64 addr_set = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 addr_req--;
339 /* Create IDE/ATA command request structure */
340 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100341 tf->lbal = (addr_req >> 0) & 0xff;
342 tf->lbam = (addr_req >>= 8) & 0xff;
343 tf->lbah = (addr_req >>= 8) & 0xff;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100344 if (lba48) {
345 tf->hob_lbal = (addr_req >>= 8) & 0xff;
346 tf->hob_lbam = (addr_req >>= 8) & 0xff;
347 tf->hob_lbah = (addr_req >>= 8) & 0xff;
348 tf->command = WIN_SET_MAX_EXT;
349 } else {
350 tf->device = (addr_req >>= 8) & 0x0f;
351 tf->command = WIN_SET_MAX;
352 }
353 tf->device |= ATA_LBA;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100354 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicza3bbb9d2008-01-25 22:17:10 +0100355 if (lba48)
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100356 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* submit command request */
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100358 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /* if OK, compute maximum address value */
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100360 if ((tf->status & 0x01) == 0)
361 addr_set = ide_get_lba_addr(tf, lba48) + 1;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 return addr_set;
364}
365
366static unsigned long long sectors_to_MB(unsigned long long n)
367{
368 n <<= 9; /* make it bytes */
369 do_div(n, 1000000); /* make it MB */
370 return n;
371}
372
373/*
374 * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
375 * so on non-buggy drives we need test only one.
376 * However, we should also check whether these fields are valid.
377 */
378static inline int idedisk_supports_hpa(const struct hd_driveid *id)
379{
380 return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
381}
382
383/*
384 * The same here.
385 */
386static inline int idedisk_supports_lba48(const struct hd_driveid *id)
387{
388 return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)
389 && id->lba_capacity_2;
390}
391
Bartlomiej Zolnierkiewiczb0244a00452007-08-20 22:42:57 +0200392/*
393 * Some disks report total number of sectors instead of
394 * maximum sector address. We list them here.
395 */
396static const struct drive_list_entry hpa_list[] = {
397 { "ST340823A", NULL },
Jorge Juan Chico7062cdc2007-09-17 12:35:30 +0200398 { "ST320413A", NULL },
Bartlomiej Zolnierkiewiczb0244a00452007-08-20 22:42:57 +0200399 { NULL, NULL }
400};
401
Arjan van de Ven858119e2006-01-14 13:20:43 -0800402static void idedisk_check_hpa(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
404 unsigned long long capacity, set_max;
405 int lba48 = idedisk_supports_lba48(drive->id);
406
407 capacity = drive->capacity64;
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100408
409 set_max = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Bartlomiej Zolnierkiewiczb0244a00452007-08-20 22:42:57 +0200411 if (ide_in_drive_list(drive->id, hpa_list)) {
412 /*
413 * Since we are inclusive wrt to firmware revisions do this
414 * extra check and apply the workaround only when needed.
415 */
416 if (set_max == capacity + 1)
417 set_max--;
418 }
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 if (set_max <= capacity)
421 return;
422
423 printk(KERN_INFO "%s: Host Protected Area detected.\n"
424 "\tcurrent capacity is %llu sectors (%llu MB)\n"
425 "\tnative capacity is %llu sectors (%llu MB)\n",
426 drive->name,
427 capacity, sectors_to_MB(capacity),
428 set_max, sectors_to_MB(set_max));
429
Bartlomiej Zolnierkiewicz7a3b7512008-01-25 22:17:06 +0100430 set_max = idedisk_set_max_address(drive, set_max, lba48);
431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 if (set_max) {
433 drive->capacity64 = set_max;
434 printk(KERN_INFO "%s: Host Protected Area disabled.\n",
435 drive->name);
436 }
437}
438
439/*
440 * Compute drive->capacity, the full capacity of the drive
441 * Called with drive->id != NULL.
442 *
443 * To compute capacity, this uses either of
444 *
445 * 1. CHS value set by user (whatever user sets will be trusted)
446 * 2. LBA value from target drive (require new ATA feature)
447 * 3. LBA value from system BIOS (new one is OK, old one may break)
448 * 4. CHS value from system BIOS (traditional style)
449 *
450 * in above order (i.e., if value of higher priority is available,
451 * reset will be ignored).
452 */
453static void init_idedisk_capacity (ide_drive_t *drive)
454{
455 struct hd_driveid *id = drive->id;
456 /*
457 * If this drive supports the Host Protected Area feature set,
458 * then we may need to change our opinion about the drive's capacity.
459 */
460 int hpa = idedisk_supports_hpa(id);
461
462 if (idedisk_supports_lba48(id)) {
463 /* drive speaks 48-bit LBA */
464 drive->select.b.lba = 1;
465 drive->capacity64 = id->lba_capacity_2;
466 if (hpa)
467 idedisk_check_hpa(drive);
468 } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
469 /* drive speaks 28-bit LBA */
470 drive->select.b.lba = 1;
471 drive->capacity64 = id->lba_capacity;
472 if (hpa)
473 idedisk_check_hpa(drive);
474 } else {
475 /* drive speaks boring old 28-bit CHS */
476 drive->capacity64 = drive->cyl * drive->head * drive->sect;
477 }
478}
479
480static sector_t idedisk_capacity (ide_drive_t *drive)
481{
482 return drive->capacity64 - drive->sect0;
483}
484
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200485#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486static int smart_enable(ide_drive_t *drive)
487{
488 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100489 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100492 tf->feature = SMART_ENABLE;
493 tf->lbam = SMART_LCYL_PASS;
494 tf->lbah = SMART_HCYL_PASS;
495 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100496 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100497 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498}
499
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200500static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
502 ide_task_t args;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100503 struct ide_taskfile *tf = &args.tf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
505 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100506 tf->feature = sub_cmd;
507 tf->nsect = 0x01;
508 tf->lbam = SMART_LCYL_PASS;
509 tf->lbah = SMART_HCYL_PASS;
510 tf->command = WIN_SMART;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100511 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100512 args.data_phase = TASKFILE_IN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 (void) smart_enable(drive);
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100514 return ide_raw_taskfile(drive, &args, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515}
516
517static int proc_idedisk_read_cache
518 (char *page, char **start, off_t off, int count, int *eof, void *data)
519{
520 ide_drive_t *drive = (ide_drive_t *) data;
521 char *out = page;
522 int len;
523
524 if (drive->id_read)
525 len = sprintf(out,"%i\n", drive->id->buf_size / 2);
526 else
527 len = sprintf(out,"(none)\n");
528 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
529}
530
531static int proc_idedisk_read_capacity
532 (char *page, char **start, off_t off, int count, int *eof, void *data)
533{
534 ide_drive_t*drive = (ide_drive_t *)data;
535 int len;
536
537 len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
538 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
539}
540
541static int proc_idedisk_read_smart_thresholds
542 (char *page, char **start, off_t off, int count, int *eof, void *data)
543{
544 ide_drive_t *drive = (ide_drive_t *)data;
545 int len = 0, i = 0;
546
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200547 if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 unsigned short *val = (unsigned short *) page;
549 char *out = ((char *)val) + (SECTOR_WORDS * 4);
550 page = out;
551 do {
552 out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
553 val += 1;
554 } while (i < (SECTOR_WORDS * 2));
555 len = out - page;
556 }
557 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
558}
559
560static int proc_idedisk_read_smart_values
561 (char *page, char **start, off_t off, int count, int *eof, void *data)
562{
563 ide_drive_t *drive = (ide_drive_t *)data;
564 int len = 0, i = 0;
565
Bartlomiej Zolnierkiewicz43e7c0c2007-10-20 00:32:37 +0200566 if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 unsigned short *val = (unsigned short *) page;
568 char *out = ((char *)val) + (SECTOR_WORDS * 4);
569 page = out;
570 do {
571 out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
572 val += 1;
573 } while (i < (SECTOR_WORDS * 2));
574 len = out - page;
575 }
576 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
577}
578
579static ide_proc_entry_t idedisk_proc[] = {
580 { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
581 { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
582 { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
583 { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL },
584 { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL },
585 { NULL, 0, NULL, NULL }
586};
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +0200587#endif /* CONFIG_IDE_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Jens Axboe165125e2007-07-24 09:28:11 +0200589static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 ide_drive_t *drive = q->queuedata;
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100592 ide_task_t task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100594 memset(&task, 0, sizeof(task));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 if (ide_id_has_flush_cache_ext(drive->id) &&
596 (drive->capacity64 >= (1UL << 28)))
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100597 task.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 else
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100599 task.tf.command = WIN_FLUSH_CACHE;
Bartlomiej Zolnierkiewiczac026ff2008-01-25 22:17:14 +0100600 task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
601 task.data_phase = TASKFILE_NO_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100603 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200604 rq->cmd_flags |= REQ_SOFTBARRIER;
Bartlomiej Zolnierkiewicz813a0eb2008-01-25 22:17:10 +0100605 rq->special = &task;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606}
607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608/*
609 * This is tightly woven into the driver->do_special can not touch.
610 * DON'T do it again until a total personality rewrite is committed.
611 */
612static int set_multcount(ide_drive_t *drive, int arg)
613{
614 struct request rq;
615
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200616 if (arg < 0 || arg > drive->id->max_multsect)
617 return -EINVAL;
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 if (drive->special.b.set_multmode)
620 return -EBUSY;
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 ide_init_drive_cmd (&rq);
Bartlomiej Zolnierkiewicz852738f2008-01-26 20:13:12 +0100623 rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 drive->mult_req = arg;
626 drive->special.b.set_multmode = 1;
627 (void) ide_do_drive_cmd (drive, &rq, ide_wait);
628 return (drive->mult_count == arg) ? 0 : -EIO;
629}
630
631static int set_nowerr(ide_drive_t *drive, int arg)
632{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200633 if (arg < 0 || arg > 1)
634 return -EINVAL;
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (ide_spin_wait_hwgroup(drive))
637 return -EBUSY;
638 drive->nowerr = arg;
639 drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
640 spin_unlock_irq(&ide_lock);
641 return 0;
642}
643
Tejun Heo3e087b52006-01-06 09:57:31 +0100644static void update_ordered(ide_drive_t *drive)
645{
646 struct hd_driveid *id = drive->id;
647 unsigned ordered = QUEUE_ORDERED_NONE;
648 prepare_flush_fn *prep_fn = NULL;
Tejun Heo3e087b52006-01-06 09:57:31 +0100649
650 if (drive->wcache) {
651 unsigned long long capacity;
652 int barrier;
653 /*
654 * We must avoid issuing commands a drive does not
655 * understand or we may crash it. We check flush cache
656 * is supported. We also check we have the LBA48 flush
657 * cache if the drive capacity is too large. By this
658 * time we have trimmed the drive capacity if LBA48 is
659 * not available so we don't need to recheck that.
660 */
661 capacity = idedisk_capacity(drive);
Jens Axboe36193482006-07-28 08:54:59 +0200662 barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
Tejun Heo3e087b52006-01-06 09:57:31 +0100663 (drive->addressing == 0 || capacity <= (1ULL << 28) ||
664 ide_id_has_flush_cache_ext(id));
665
666 printk(KERN_INFO "%s: cache flushes %ssupported\n",
Jean Delvaref7ad8362006-02-03 03:04:57 -0800667 drive->name, barrier ? "" : "not ");
Tejun Heo3e087b52006-01-06 09:57:31 +0100668
669 if (barrier) {
670 ordered = QUEUE_ORDERED_DRAIN_FLUSH;
671 prep_fn = idedisk_prepare_flush;
Tejun Heo3e087b52006-01-06 09:57:31 +0100672 }
673 } else
674 ordered = QUEUE_ORDERED_DRAIN;
675
676 blk_queue_ordered(drive->queue, ordered, prep_fn);
Tejun Heo3e087b52006-01-06 09:57:31 +0100677}
678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679static int write_cache(ide_drive_t *drive, int arg)
680{
681 ide_task_t args;
Tejun Heo3e087b52006-01-06 09:57:31 +0100682 int err = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200684 if (arg < 0 || arg > 1)
685 return -EINVAL;
686
Tejun Heo3e087b52006-01-06 09:57:31 +0100687 if (ide_id_has_flush_cache(drive->id)) {
688 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100689 args.tf.feature = arg ?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100691 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100692 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100693 err = ide_no_data_taskfile(drive, &args);
Tejun Heo3e087b52006-01-06 09:57:31 +0100694 if (err == 0)
695 drive->wcache = arg;
696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Tejun Heo3e087b52006-01-06 09:57:31 +0100698 update_ordered(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Tejun Heo3e087b52006-01-06 09:57:31 +0100700 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703static int do_idedisk_flushcache (ide_drive_t *drive)
704{
705 ide_task_t args;
706
707 memset(&args, 0, sizeof(ide_task_t));
708 if (ide_id_has_flush_cache_ext(drive->id))
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100709 args.tf.command = WIN_FLUSH_CACHE_EXT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 else
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100711 args.tf.command = WIN_FLUSH_CACHE;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100712 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100713 return ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
716static int set_acoustic (ide_drive_t *drive, int arg)
717{
718 ide_task_t args;
719
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200720 if (arg < 0 || arg > 254)
721 return -EINVAL;
722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 memset(&args, 0, sizeof(ide_task_t));
Bartlomiej Zolnierkiewicz650d8412008-01-25 22:17:06 +0100724 args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
725 args.tf.nsect = arg;
726 args.tf.command = WIN_SETFEATURES;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100727 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz9a3c49b2008-01-25 22:17:07 +0100728 ide_no_data_taskfile(drive, &args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 drive->acoustic = arg;
730 return 0;
731}
732
733/*
734 * drive->addressing:
735 * 0: 28-bit
736 * 1: 48-bit
737 * 2: 48-bit capable doing 28-bit
738 */
739static int set_lba_addressing(ide_drive_t *drive, int arg)
740{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200741 if (arg < 0 || arg > 2)
742 return -EINVAL;
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 drive->addressing = 0;
745
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200746 if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return 0;
748
749 if (!idedisk_supports_lba48(drive->id))
750 return -EIO;
751 drive->addressing = arg;
752 return 0;
753}
754
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200755#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756static void idedisk_add_settings(ide_drive_t *drive)
757{
758 struct hd_driveid *id = drive->id;
759
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200760 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL);
761 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
762 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
763 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +0200764 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount);
765 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
766 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
767 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache);
768 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic);
769 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
770 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200772#else
773static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
774#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776static void idedisk_setup (ide_drive_t *drive)
777{
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200778 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 struct hd_driveid *id = drive->id;
780 unsigned long long capacity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
782 idedisk_add_settings(drive);
783
784 if (drive->id_read == 0)
785 return;
786
Richard Purdie98109332006-02-03 03:04:55 -0800787 if (drive->removable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /*
789 * Removable disks (eg. SYQUEST); ignore 'WD' drives
790 */
791 if (id->model[0] != 'W' || id->model[1] != 'D') {
792 drive->doorlocking = 1;
793 }
794 }
795
796 (void)set_lba_addressing(drive, 1);
797
798 if (drive->addressing == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 int max_s = 2048;
800
801 if (max_s > hwif->rqsize)
802 max_s = hwif->rqsize;
803
804 blk_queue_max_sectors(drive->queue, max_s);
805 }
806
807 printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
808
809 /* calculate drive capacity, and select LBA if possible */
810 init_idedisk_capacity (drive);
811
812 /* limit drive capacity to 137GB if LBA48 cannot be used */
813 if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
814 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
815 "%llu sectors (%llu MB)\n",
816 drive->name, (unsigned long long)drive->capacity64,
817 sectors_to_MB(drive->capacity64));
818 drive->capacity64 = 1ULL << 28;
819 }
820
Bartlomiej Zolnierkiewicz238e4f12007-10-19 00:30:07 +0200821 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 if (drive->capacity64 > 1ULL << 28) {
823 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
824 " be used for accessing sectors > %u\n",
825 drive->name, 1 << 28);
826 } else
827 drive->addressing = 0;
828 }
829
830 /*
831 * if possible, give fdisk access to more of the drive,
832 * by correcting bios_cyls:
833 */
834 capacity = idedisk_capacity (drive);
835 if (!drive->forced_geom) {
836
837 if (idedisk_supports_lba48(drive->id)) {
838 /* compatibility */
839 drive->bios_sect = 63;
840 drive->bios_head = 255;
841 }
842
843 if (drive->bios_sect && drive->bios_head) {
844 unsigned int cap0 = capacity; /* truncate to 32 bits */
845 unsigned int cylsz, cyl;
846
847 if (cap0 != capacity)
848 drive->bios_cyl = 65535;
849 else {
850 cylsz = drive->bios_sect * drive->bios_head;
851 cyl = cap0 / cylsz;
852 if (cyl > 65535)
853 cyl = 65535;
854 if (cyl > drive->bios_cyl)
855 drive->bios_cyl = cyl;
856 }
857 }
858 }
859 printk(KERN_INFO "%s: %llu sectors (%llu MB)",
860 drive->name, capacity, sectors_to_MB(capacity));
861
862 /* Only print cache size when it was specified */
863 if (id->buf_size)
864 printk (" w/%dKiB Cache", id->buf_size/2);
865
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +0100866 printk(KERN_CONT ", CHS=%d/%d/%d\n",
867 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 /* write cache enabled? */
870 if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
871 drive->wcache = 1;
872
873 write_cache(drive, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
876static void ide_cacheflush_p(ide_drive_t *drive)
877{
878 if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
879 return;
880
881 if (do_idedisk_flushcache(drive))
882 printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
883}
884
Russell King4031bbe2006-01-06 11:41:00 +0000885static void ide_disk_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
887 struct ide_disk_obj *idkp = drive->driver_data;
888 struct gendisk *g = idkp->disk;
889
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200890 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 del_gendisk(g);
893
Bartlomiej Zolnierkiewiczd36fef62005-12-15 02:19:20 +0100894 ide_cacheflush_p(drive);
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 ide_disk_put(idkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897}
898
899static void ide_disk_release(struct kref *kref)
900{
901 struct ide_disk_obj *idkp = to_ide_disk(kref);
902 ide_drive_t *drive = idkp->drive;
903 struct gendisk *g = idkp->disk;
904
905 drive->driver_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 g->private_data = NULL;
907 put_disk(g);
908 kfree(idkp);
909}
910
Russell King4031bbe2006-01-06 11:41:00 +0000911static int ide_disk_probe(ide_drive_t *drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Lee Trager0d2157f2007-06-08 15:14:30 +0200913/*
914 * On HPA drives the capacity needs to be
915 * reinitilized on resume otherwise the disk
916 * can not be used and a hard reset is required
917 */
918static void ide_disk_resume(ide_drive_t *drive)
919{
920 if (idedisk_supports_hpa(drive->id))
921 init_idedisk_capacity(drive);
922}
923
Russell King4031bbe2006-01-06 11:41:00 +0000924static void ide_device_shutdown(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926#ifdef CONFIG_ALPHA
927 /* On Alpha, halt(8) doesn't actually turn the machine off,
928 it puts you into the sort of firmware monitor. Typically,
929 it's used to boot another kernel image, so it's not much
930 different from reboot(8). Therefore, we don't need to
931 spin down the disk in this case, especially since Alpha
932 firmware doesn't handle disks in standby mode properly.
933 On the other hand, it's reasonably safe to turn the power
934 off when the shutdown process reaches the firmware prompt,
935 as the firmware initialization takes rather long time -
936 at least 10 seconds, which should be sufficient for
937 the disk to expire its write cache. */
938 if (system_state != SYSTEM_POWER_OFF) {
939#else
940 if (system_state == SYSTEM_RESTART) {
941#endif
942 ide_cacheflush_p(drive);
943 return;
944 }
945
946 printk("Shutdown: %s\n", drive->name);
Russell King4031bbe2006-01-06 11:41:00 +0000947 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948}
949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950static ide_driver_t idedisk_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +0100952 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +0200953 .name = "ide-disk",
954 .bus = &ide_bus_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 },
Russell King4031bbe2006-01-06 11:41:00 +0000956 .probe = ide_disk_probe,
957 .remove = ide_disk_remove,
Lee Trager0d2157f2007-06-08 15:14:30 +0200958 .resume = ide_disk_resume,
Russell King4031bbe2006-01-06 11:41:00 +0000959 .shutdown = ide_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 .version = IDEDISK_VERSION,
961 .media = ide_disk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 .supports_dsc_overlap = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 .do_request = ide_do_rw_disk,
964 .end_request = ide_end_request,
965 .error = __ide_error,
966 .abort = __ide_abort,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200967#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 .proc = idedisk_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +0200969#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970};
971
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100972static int idedisk_set_doorlock(ide_drive_t *drive, int on)
973{
974 ide_task_t task;
975
976 memset(&task, 0, sizeof(task));
977 task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Bartlomiej Zolnierkiewicz657cc1a2008-01-26 20:13:10 +0100978 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +0100979
980 return ide_no_data_taskfile(drive, &task);
981}
982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983static int idedisk_open(struct inode *inode, struct file *filp)
984{
985 struct gendisk *disk = inode->i_bdev->bd_disk;
986 struct ide_disk_obj *idkp;
987 ide_drive_t *drive;
988
989 if (!(idkp = ide_disk_get(disk)))
990 return -ENXIO;
991
992 drive = idkp->drive;
993
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +0100994 idkp->openers++;
995
996 if (drive->removable && idkp->openers == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 check_disk_change(inode->i_bdev);
998 /*
999 * Ignore the return code from door_lock,
1000 * since the open() has already succeeded,
1001 * and the door_lock is irrelevant at this point.
1002 */
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001003 if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 drive->doorlocking = 0;
1005 }
1006 return 0;
1007}
1008
1009static int idedisk_release(struct inode *inode, struct file *filp)
1010{
1011 struct gendisk *disk = inode->i_bdev->bd_disk;
1012 struct ide_disk_obj *idkp = ide_disk_g(disk);
1013 ide_drive_t *drive = idkp->drive;
1014
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001015 if (idkp->openers == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 ide_cacheflush_p(drive);
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001017
1018 if (drive->removable && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz29ec6832008-01-26 20:12:59 +01001019 if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 drive->doorlocking = 0;
1021 }
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01001022
1023 idkp->openers--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
1025 ide_disk_put(idkp);
1026
1027 return 0;
1028}
1029
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001030static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1031{
1032 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1033 ide_drive_t *drive = idkp->drive;
1034
1035 geo->heads = drive->bios_head;
1036 geo->sectors = drive->bios_sect;
1037 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1038 return 0;
1039}
1040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041static int idedisk_ioctl(struct inode *inode, struct file *file,
1042 unsigned int cmd, unsigned long arg)
1043{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001044 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 struct block_device *bdev = inode->i_bdev;
1046 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001047 ide_drive_t *drive = idkp->drive;
1048 int err, (*setfunc)(ide_drive_t *, int);
1049 u8 *val;
1050
1051 switch (cmd) {
1052 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
1053 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
1054 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
1055 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
1056 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
1057 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1058 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1059 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1060 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
1061 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1062 }
1063
1064 return generic_ide_ioctl(drive, file, bdev, cmd, arg);
1065
1066read_val:
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001067 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001068 spin_lock_irqsave(&ide_lock, flags);
1069 err = *val;
1070 spin_unlock_irqrestore(&ide_lock, flags);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001071 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001072 return err >= 0 ? put_user(err, (long __user *)arg) : err;
1073
1074set_val:
1075 if (bdev != bdev->bd_contains)
1076 err = -EINVAL;
1077 else {
1078 if (!capable(CAP_SYS_ADMIN))
1079 err = -EACCES;
1080 else {
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001081 mutex_lock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001082 err = setfunc(drive, arg);
Matthias Kaehlckef9383c42007-07-09 23:17:56 +02001083 mutex_unlock(&ide_setting_mtx);
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001084 }
1085 }
1086 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087}
1088
1089static int idedisk_media_changed(struct gendisk *disk)
1090{
1091 struct ide_disk_obj *idkp = ide_disk_g(disk);
1092 ide_drive_t *drive = idkp->drive;
1093
1094 /* do not scan partitions twice if this is a removable device */
1095 if (drive->attach) {
1096 drive->attach = 0;
1097 return 0;
1098 }
1099 /* if removable, always assume it was changed */
1100 return drive->removable;
1101}
1102
1103static int idedisk_revalidate_disk(struct gendisk *disk)
1104{
1105 struct ide_disk_obj *idkp = ide_disk_g(disk);
1106 set_capacity(disk, idedisk_capacity(idkp->drive));
1107 return 0;
1108}
1109
1110static struct block_device_operations idedisk_ops = {
1111 .owner = THIS_MODULE,
1112 .open = idedisk_open,
1113 .release = idedisk_release,
1114 .ioctl = idedisk_ioctl,
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08001115 .getgeo = idedisk_getgeo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 .media_changed = idedisk_media_changed,
1117 .revalidate_disk= idedisk_revalidate_disk
1118};
1119
1120MODULE_DESCRIPTION("ATA DISK Driver");
1121
Russell King4031bbe2006-01-06 11:41:00 +00001122static int ide_disk_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
1124 struct ide_disk_obj *idkp;
1125 struct gendisk *g;
1126
1127 /* strstr("foo", "") is non-NULL */
1128 if (!strstr("ide-disk", drive->driver_req))
1129 goto failed;
1130 if (!drive->present)
1131 goto failed;
1132 if (drive->media != ide_disk)
1133 goto failed;
1134
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08001135 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 if (!idkp)
1137 goto failed;
1138
Christoph Lameter19460892005-06-23 00:08:19 -07001139 g = alloc_disk_node(1 << PARTN_BITS,
Christoph Lameter86b37862005-08-09 19:59:21 -07001140 hwif_to_node(drive->hwif));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 if (!g)
1142 goto out_free_idkp;
1143
1144 ide_init_disk(g, drive);
1145
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001146 ide_proc_register_driver(drive, &idedisk_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 kref_init(&idkp->kref);
1149
1150 idkp->drive = drive;
1151 idkp->driver = &idedisk_driver;
1152 idkp->disk = g;
1153
1154 g->private_data = &idkp->driver;
1155
1156 drive->driver_data = idkp;
1157
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 idedisk_setup(drive);
1159 if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
1160 printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
1161 drive->name, drive->head);
1162 drive->attach = 0;
1163 } else
1164 drive->attach = 1;
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 g->minors = 1 << PARTN_BITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 g->driverfs_dev = &drive->gendev;
1168 g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
1169 set_capacity(g, idedisk_capacity(drive));
1170 g->fops = &idedisk_ops;
1171 add_disk(g);
1172 return 0;
1173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174out_free_idkp:
1175 kfree(idkp);
1176failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001177 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178}
1179
1180static void __exit idedisk_exit (void)
1181{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001182 driver_unregister(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183}
1184
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01001185static int __init idedisk_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001187 return driver_register(&idedisk_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188}
1189
Kay Sievers263756e2005-12-12 18:03:44 +01001190MODULE_ALIAS("ide:*m-disk*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191module_init(idedisk_init);
1192module_exit(idedisk_exit);
1193MODULE_LICENSE("GPL");