ide-disk.c 19.3 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
Linus Torvalds's avatar
Linus Torvalds committed
2
/*
3 4 5
 *  Copyright (C) 1994-1998	   Linus Torvalds & authors (see below)
 *  Copyright (C) 1998-2002	   Linux ATA Development
 *				      Andre Hedrick <andre@linux-ide.org>
6
 *  Copyright (C) 2003		   Red Hat
7
 *  Copyright (C) 2003-2005, 2007  Bartlomiej Zolnierkiewicz
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 */

/*
 *  Mostly written by Mark Lord <mlord@pobox.com>
 *                and Gadi Oxman <gadio@netvision.net.il>
 *                and Andre Hedrick <andre@linux-ide.org>
 *
 * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
 */

#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/delay.h>
29
#include <linux/mutex.h>
30
#include <linux/leds.h>
Linus Torvalds's avatar
Linus Torvalds committed
31 32 33 34
#include <linux/ide.h>

#include <asm/byteorder.h>
#include <asm/irq.h>
35
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
36 37 38
#include <asm/io.h>
#include <asm/div64.h>

39
#include "ide-disk.h"
Linus Torvalds's avatar
Linus Torvalds committed
40

41
static const u8 ide_rw_cmds[] = {
42 43 44 45 46 47 48 49 50 51 52 53
	ATA_CMD_READ_MULTI,
	ATA_CMD_WRITE_MULTI,
	ATA_CMD_READ_MULTI_EXT,
	ATA_CMD_WRITE_MULTI_EXT,
	ATA_CMD_PIO_READ,
	ATA_CMD_PIO_WRITE,
	ATA_CMD_PIO_READ_EXT,
	ATA_CMD_PIO_WRITE_EXT,
	ATA_CMD_READ,
	ATA_CMD_WRITE,
	ATA_CMD_READ_EXT,
	ATA_CMD_WRITE_EXT,
54 55
};

56
static void ide_tf_set_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 dma)
57 58 59
{
	u8 index, lba48, write;

60 61
	lba48 = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
	write = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
62

63 64
	if (dma) {
		cmd->protocol = ATA_PROT_DMA;
65
		index = 8;
66 67 68 69 70 71 72 73
	} else {
		cmd->protocol = ATA_PROT_PIO;
		if (drive->mult_count) {
			cmd->tf_flags |= IDE_TFLAG_MULTI_PIO;
			index = 0;
		} else
			index = 4;
	}
74

75
	cmd->tf.command = ide_rw_cmds[index + lba48 + write];
76 77
}

Linus Torvalds's avatar
Linus Torvalds committed
78 79 80 81
/*
 * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
 * using LBA if supported, or CHS otherwise, to address sectors.
 */
82 83
static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
					sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
84
{
85
	ide_hwif_t *hwif	= drive->hwif;
86
	u16 nsectors		= (u16)blk_rq_sectors(rq);
87 88
	u8 lba48		= !!(drive->dev_flags & IDE_DFLAG_LBA48);
	u8 dma			= !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
89 90
	struct ide_cmd		cmd;
	struct ide_taskfile	*tf = &cmd.tf;
91
	ide_startstop_t		rc;
Linus Torvalds's avatar
Linus Torvalds committed
92

93
	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
94
		if (block + blk_rq_sectors(rq) > 1ULL << 28)
Linus Torvalds's avatar
Linus Torvalds committed
95 96 97 98 99
			dma = 0;
		else
			lba48 = 0;
	}

100
	memset(&cmd, 0, sizeof(cmd));
101 102
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
103

104
	if (drive->dev_flags & IDE_DFLAG_LBA) {
Linus Torvalds's avatar
Linus Torvalds committed
105
		if (lba48) {
106 107
			pr_debug("%s: LBA=0x%012llx\n", drive->name,
					(unsigned long long)block);
Linus Torvalds's avatar
Linus Torvalds committed
108

109
			tf->nsect  = nsectors & 0xff;
110 111 112
			tf->lbal   = (u8) block;
			tf->lbam   = (u8)(block >>  8);
			tf->lbah   = (u8)(block >> 16);
113 114 115 116 117 118 119 120 121
			tf->device = ATA_LBA;

			tf = &cmd.hob;
			tf->nsect = (nsectors >> 8) & 0xff;
			tf->lbal  = (u8)(block >> 24);
			if (sizeof(block) != 4) {
				tf->lbam = (u8)((u64)block >> 32);
				tf->lbah = (u8)((u64)block >> 40);
			}
122

123 124 125
			cmd.valid.out.hob = IDE_VALID_OUT_HOB;
			cmd.valid.in.hob  = IDE_VALID_IN_HOB;
			cmd.tf_flags |= IDE_TFLAG_LBA48;
Linus Torvalds's avatar
Linus Torvalds committed
126
		} else {
127
			tf->nsect  = nsectors & 0xff;
128 129 130
			tf->lbal   = block;
			tf->lbam   = block >>= 8;
			tf->lbah   = block >>= 8;
131
			tf->device = ((block >> 8) & 0xf) | ATA_LBA;
Linus Torvalds's avatar
Linus Torvalds committed
132 133
		}
	} else {
134 135
		unsigned int sect, head, cyl, track;

Linus Torvalds's avatar
Linus Torvalds committed
136 137 138 139 140 141 142
		track = (int)block / drive->sect;
		sect  = (int)block % drive->sect + 1;
		head  = track % drive->head;
		cyl   = track / drive->head;

		pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);

143
		tf->nsect  = nsectors & 0xff;
144 145 146 147
		tf->lbal   = sect;
		tf->lbam   = cyl;
		tf->lbah   = cyl >> 8;
		tf->device = head;
Linus Torvalds's avatar
Linus Torvalds committed
148 149
	}

150 151
	cmd.tf_flags |= IDE_TFLAG_FS;

152
	if (rq_data_dir(rq))
153
		cmd.tf_flags |= IDE_TFLAG_WRITE;
154

155 156
	ide_tf_set_cmd(drive, &cmd, dma);
	cmd.rq = rq;
157

158
	if (dma == 0) {
159
		ide_init_sg_cmd(&cmd, nsectors << 9);
160 161 162
		ide_map_sg(drive, &cmd);
	}

163
	rc = do_rw_taskfile(drive, &cmd);
164

165
	if (rc == ide_stopped && dma) {
Linus Torvalds's avatar
Linus Torvalds committed
166
		/* fallback to PIO */
167 168
		cmd.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
		ide_tf_set_cmd(drive, &cmd, 0);
169
		ide_init_sg_cmd(&cmd, nsectors << 9);
170
		rc = do_rw_taskfile(drive, &cmd);
Linus Torvalds's avatar
Linus Torvalds committed
171 172
	}

173
	return rc;
Linus Torvalds's avatar
Linus Torvalds committed
174 175 176 177 178 179 180 181
}

/*
 * 268435455  == 137439 MB or 28bit limit
 * 320173056  == 163929 MB or 48bit addressing
 * 1073741822 == 549756 MB or 48bit addressing fake drive
 */

182 183
static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
				      sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
184
{
185
	ide_hwif_t *hwif = drive->hwif;
Linus Torvalds's avatar
Linus Torvalds committed
186

187
	BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
188
	BUG_ON(blk_rq_is_passthrough(rq));
Linus Torvalds's avatar
Linus Torvalds committed
189

190
	ledtrig_disk_activity(rq_data_dir(rq) == WRITE);
191

192
	pr_debug("%s: %sing: block=%llu, sectors=%u\n",
Linus Torvalds's avatar
Linus Torvalds committed
193
		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
194
		 (unsigned long long)block, blk_rq_sectors(rq));
Linus Torvalds's avatar
Linus Torvalds committed
195 196 197 198 199 200 201 202 203 204 205

	if (hwif->rw_disk)
		hwif->rw_disk(drive, rq);

	return __ide_do_rw_disk(drive, rq, block);
}

/*
 * Queries for true maximum capacity of the drive.
 * Returns maximum LBA address (> 0) of the drive, 0 if failed.
 */
206
static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
Linus Torvalds's avatar
Linus Torvalds committed
207
{
208 209
	struct ide_cmd cmd;
	struct ide_taskfile *tf = &cmd.tf;
210
	u64 addr = 0;
Linus Torvalds's avatar
Linus Torvalds committed
211

212
	memset(&cmd, 0, sizeof(cmd));
213
	if (lba48)
214
		tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
215
	else
216
		tf->command = ATA_CMD_READ_NATIVE_MAX;
217
	tf->device  = ATA_LBA;
218

219 220 221 222 223 224 225
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
	if (lba48) {
		cmd.valid.out.hob = IDE_VALID_OUT_HOB;
		cmd.valid.in.hob  = IDE_VALID_IN_HOB;
		cmd.tf_flags = IDE_TFLAG_LBA48;
	}
226 227

	ide_no_data_taskfile(drive, &cmd);
Linus Torvalds's avatar
Linus Torvalds committed
228 229

	/* if OK, compute maximum address value */
Sergei Shtylyov's avatar
Sergei Shtylyov committed
230
	if (!(tf->status & ATA_ERR))
231
		addr = ide_get_lba_addr(&cmd, lba48) + 1;
232

Linus Torvalds's avatar
Linus Torvalds committed
233 234 235 236 237 238 239
	return addr;
}

/*
 * Sets maximum virtual LBA address of the drive.
 * Returns new maximum virtual LBA address (> 0) or 0 on failure.
 */
240
static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
Linus Torvalds's avatar
Linus Torvalds committed
241
{
242 243
	struct ide_cmd cmd;
	struct ide_taskfile *tf = &cmd.tf;
244
	u64 addr_set = 0;
Linus Torvalds's avatar
Linus Torvalds committed
245 246

	addr_req--;
247 248

	memset(&cmd, 0, sizeof(cmd));
249 250 251
	tf->lbal     = (addr_req >>  0) & 0xff;
	tf->lbam     = (addr_req >>= 8) & 0xff;
	tf->lbah     = (addr_req >>= 8) & 0xff;
252
	if (lba48) {
253 254 255
		cmd.hob.lbal = (addr_req >>= 8) & 0xff;
		cmd.hob.lbam = (addr_req >>= 8) & 0xff;
		cmd.hob.lbah = (addr_req >>= 8) & 0xff;
256
		tf->command  = ATA_CMD_SET_MAX_EXT;
257 258
	} else {
		tf->device   = (addr_req >>= 8) & 0x0f;
259
		tf->command  = ATA_CMD_SET_MAX;
260 261
	}
	tf->device |= ATA_LBA;
262

263 264 265 266 267 268 269
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
	if (lba48) {
		cmd.valid.out.hob = IDE_VALID_OUT_HOB;
		cmd.valid.in.hob  = IDE_VALID_IN_HOB;
		cmd.tf_flags = IDE_TFLAG_LBA48;
	}
270 271 272

	ide_no_data_taskfile(drive, &cmd);

Linus Torvalds's avatar
Linus Torvalds committed
273
	/* if OK, compute maximum address value */
Sergei Shtylyov's avatar
Sergei Shtylyov committed
274
	if (!(tf->status & ATA_ERR))
275
		addr_set = ide_get_lba_addr(&cmd, lba48) + 1;
276

Linus Torvalds's avatar
Linus Torvalds committed
277 278 279 280 281 282 283 284 285 286
	return addr_set;
}

static unsigned long long sectors_to_MB(unsigned long long n)
{
	n <<= 9;		/* make it bytes */
	do_div(n, 1000000);	/* make it MB */
	return n;
}

287 288 289 290 291 292
/*
 * Some disks report total number of sectors instead of
 * maximum sector address.  We list them here.
 */
static const struct drive_list_entry hpa_list[] = {
	{ "ST340823A",	NULL },
293
	{ "ST320413A",	NULL },
294
	{ "ST310211A",	NULL },
295 296 297
	{ NULL,		NULL }
};

298
static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48)
Linus Torvalds's avatar
Linus Torvalds committed
299
{
300
	u64 capacity, set_max;
Linus Torvalds's avatar
Linus Torvalds committed
301 302

	capacity = drive->capacity64;
303
	set_max  = idedisk_read_native_max_address(drive, lba48);
Linus Torvalds's avatar
Linus Torvalds committed
304

305 306 307 308 309 310 311 312 313
	if (ide_in_drive_list(drive->id, hpa_list)) {
		/*
		 * Since we are inclusive wrt to firmware revisions do this
		 * extra check and apply the workaround only when needed.
		 */
		if (set_max == capacity + 1)
			set_max--;
	}

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	return set_max;
}

static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48)
{
	set_max = idedisk_set_max_address(drive, set_max, lba48);
	if (set_max)
		drive->capacity64 = set_max;

	return set_max;
}

static void idedisk_check_hpa(ide_drive_t *drive)
{
	u64 capacity, set_max;
	int lba48 = ata_id_lba48_enabled(drive->id);

	capacity = drive->capacity64;
	set_max  = ide_disk_hpa_get_native_capacity(drive, lba48);

Linus Torvalds's avatar
Linus Torvalds committed
334 335 336
	if (set_max <= capacity)
		return;

337 338
	drive->probed_capacity = set_max;

Linus Torvalds's avatar
Linus Torvalds committed
339 340 341 342 343 344 345
	printk(KERN_INFO "%s: Host Protected Area detected.\n"
			 "\tcurrent capacity is %llu sectors (%llu MB)\n"
			 "\tnative  capacity is %llu sectors (%llu MB)\n",
			 drive->name,
			 capacity, sectors_to_MB(capacity),
			 set_max, sectors_to_MB(set_max));

346 347
	if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0)
		return;
348

349 350
	set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48);
	if (set_max)
Linus Torvalds's avatar
Linus Torvalds committed
351 352 353 354
		printk(KERN_INFO "%s: Host Protected Area disabled.\n",
				 drive->name);
}

355
static int ide_disk_get_capacity(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
356
{
357
	u16 *id = drive->id;
358
	int lba;
Linus Torvalds's avatar
Linus Torvalds committed
359

360
	if (ata_id_lba48_enabled(id)) {
Linus Torvalds's avatar
Linus Torvalds committed
361
		/* drive speaks 48-bit LBA */
362
		lba = 1;
363
		drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
364
	} else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
Linus Torvalds's avatar
Linus Torvalds committed
365
		/* drive speaks 28-bit LBA */
366
		lba = 1;
367
		drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
Linus Torvalds's avatar
Linus Torvalds committed
368 369
	} else {
		/* drive speaks boring old 28-bit CHS */
370
		lba = 0;
Linus Torvalds's avatar
Linus Torvalds committed
371 372
		drive->capacity64 = drive->cyl * drive->head * drive->sect;
	}
373

374 375
	drive->probed_capacity = drive->capacity64;

376 377 378 379 380 381 382 383 384 385
	if (lba) {
		drive->dev_flags |= IDE_DFLAG_LBA;

		/*
		* If this device supports the Host Protected Area feature set,
		* then we may need to change our opinion about its capacity.
		*/
		if (ata_id_hpa_enabled(id))
			idedisk_check_hpa(drive);
	}
386 387 388 389 390 391 392 393

	/* limit drive capacity to 137GB if LBA48 cannot be used */
	if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
	    drive->capacity64 > 1ULL << 28) {
		printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
		       "%llu sectors (%llu MB)\n",
		       drive->name, (unsigned long long)drive->capacity64,
		       sectors_to_MB(drive->capacity64));
394
		drive->probed_capacity = drive->capacity64 = 1ULL << 28;
395 396 397 398 399 400 401 402 403 404 405
	}

	if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
	    (drive->dev_flags & IDE_DFLAG_LBA48)) {
		if (drive->capacity64 > 1ULL << 28) {
			printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
					 " will be used for accessing sectors "
					 "> %u\n", drive->name, 1 << 28);
		} else
			drive->dev_flags &= ~IDE_DFLAG_LBA48;
	}
406 407

	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
408 409
}

410
static void ide_disk_unlock_native_capacity(ide_drive_t *drive)
411 412 413 414 415 416
{
	u16 *id = drive->id;
	int lba48 = ata_id_lba48_enabled(id);

	if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 ||
	    ata_id_hpa_enabled(id) == 0)
417
		return;
418 419 420 421 422

	/*
	 * according to the spec the SET MAX ADDRESS command shall be
	 * immediately preceded by a READ NATIVE MAX ADDRESS command
	 */
423 424 425 426 427
	if (!ide_disk_hpa_get_native_capacity(drive, lba48))
		return;

	if (ide_disk_hpa_set_capacity(drive, drive->probed_capacity, lba48))
		drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */
428 429
}

430
static bool idedisk_prep_rq(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
431
{
432 433
	struct ide_cmd *cmd;

434
	if (req_op(rq) != REQ_OP_FLUSH)
435
		return true;
436

437 438
	if (ide_req(rq)->special) {
		cmd = ide_req(rq)->special;
439 440 441 442
		memset(cmd, 0, sizeof(*cmd));
	} else {
		cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
	}
Linus Torvalds's avatar
Linus Torvalds committed
443

444
	/* FIXME: map struct ide_taskfile on rq->cmd[] */
445
	BUG_ON(cmd == NULL);
446

447
	if (ata_id_flush_ext_enabled(drive->id) &&
Linus Torvalds's avatar
Linus Torvalds committed
448
	    (drive->capacity64 >= (1UL << 28)))
449
		cmd->tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds's avatar
Linus Torvalds committed
450
	else
451
		cmd->tf.command = ATA_CMD_FLUSH;
452 453
	cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd->tf_flags = IDE_TFLAG_DYN;
454
	cmd->protocol = ATA_PROT_NODATA;
455 456
	rq->cmd_flags &= ~REQ_OP_MASK;
	rq->cmd_flags |= REQ_OP_DRV_OUT;
457
	ide_req(rq)->type = ATA_PRIV_TASKFILE;
458
	ide_req(rq)->special = cmd;
459
	cmd->rq = rq;
460

461
	return true;
Linus Torvalds's avatar
Linus Torvalds committed
462 463
}

464 465
ide_devset_get(multcount, mult_count);

Linus Torvalds's avatar
Linus Torvalds committed
466 467 468 469 470 471
/*
 * This is tightly woven into the driver->do_special can not touch.
 * DON'T do it again until a total personality rewrite is committed.
 */
static int set_multcount(ide_drive_t *drive, int arg)
{
472
	struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
473

474
	if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
475 476
		return -EINVAL;

477
	if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
Linus Torvalds's avatar
Linus Torvalds committed
478
		return -EBUSY;
479

480
	rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0);
481
	ide_req(rq)->type = ATA_PRIV_TASKFILE;
482

Linus Torvalds's avatar
Linus Torvalds committed
483
	drive->mult_req = arg;
484
	drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
485
	blk_execute_rq(drive->queue, NULL, rq, 0);
486
	blk_put_request(rq);
487

Linus Torvalds's avatar
Linus Torvalds committed
488 489 490
	return (drive->mult_count == arg) ? 0 : -EIO;
}

491
ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
492

Linus Torvalds's avatar
Linus Torvalds committed
493 494
static int set_nowerr(ide_drive_t *drive, int arg)
{
495 496 497
	if (arg < 0 || arg > 1)
		return -EINVAL;

498 499 500 501 502
	if (arg)
		drive->dev_flags |= IDE_DFLAG_NOWERR;
	else
		drive->dev_flags &= ~IDE_DFLAG_NOWERR;

Linus Torvalds's avatar
Linus Torvalds committed
503
	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
504

Linus Torvalds's avatar
Linus Torvalds committed
505 506 507
	return 0;
}

508 509
static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
{
510
	struct ide_cmd cmd;
511

512 513 514 515
	memset(&cmd, 0, sizeof(cmd));
	cmd.tf.feature = feature;
	cmd.tf.nsect   = nsect;
	cmd.tf.command = ATA_CMD_SET_FEATURES;
516 517
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
518

519
	return ide_no_data_taskfile(drive, &cmd);
520 521
}

522
static void update_flush(ide_drive_t *drive)
523
{
524
	u16 *id = drive->id;
525
	bool wc = false;
526

527
	if (drive->dev_flags & IDE_DFLAG_WCACHE) {
528 529 530 531 532 533 534 535 536 537
		unsigned long long capacity;
		int barrier;
		/*
		 * We must avoid issuing commands a drive does not
		 * understand or we may crash it. We check flush cache
		 * is supported. We also check we have the LBA48 flush
		 * cache if the drive capacity is too large. By this
		 * time we have trimmed the drive capacity if LBA48 is
		 * not available so we don't need to recheck that.
		 */
538
		capacity = ide_gd_capacity(drive);
539 540 541 542
		barrier = ata_id_flush_enabled(id) &&
			(drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
			((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
			 capacity <= (1ULL << 28) ||
543
			 ata_id_flush_ext_enabled(id));
544 545

		printk(KERN_INFO "%s: cache flushes %ssupported\n",
546
		       drive->name, barrier ? "" : "not ");
547 548

		if (barrier) {
549
			wc = true;
550
			drive->prep_rq = idedisk_prep_rq;
551
		}
552
	}
553

554
	blk_queue_write_cache(drive->queue, wc, false);
555 556
}

557
ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
558 559

static int set_wcache(ide_drive_t *drive, int arg)
Linus Torvalds's avatar
Linus Torvalds committed
560
{
561
	int err = 1;
Linus Torvalds's avatar
Linus Torvalds committed
562

563 564 565
	if (arg < 0 || arg > 1)
		return -EINVAL;

566
	if (ata_id_flush_enabled(drive->id)) {
567 568
		err = ide_do_setfeature(drive,
			arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
569 570 571 572 573 574
		if (err == 0) {
			if (arg)
				drive->dev_flags |= IDE_DFLAG_WCACHE;
			else
				drive->dev_flags &= ~IDE_DFLAG_WCACHE;
		}
575
	}
Linus Torvalds's avatar
Linus Torvalds committed
576

577
	update_flush(drive);
Linus Torvalds's avatar
Linus Torvalds committed
578

579
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
580 581
}

582
static int do_idedisk_flushcache(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
583
{
584
	struct ide_cmd cmd;
Linus Torvalds's avatar
Linus Torvalds committed
585

586
	memset(&cmd, 0, sizeof(cmd));
587
	if (ata_id_flush_ext_enabled(drive->id))
588
		cmd.tf.command = ATA_CMD_FLUSH_EXT;
Linus Torvalds's avatar
Linus Torvalds committed
589
	else
590
		cmd.tf.command = ATA_CMD_FLUSH;
591 592
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
593 594

	return ide_no_data_taskfile(drive, &cmd);
Linus Torvalds's avatar
Linus Torvalds committed
595 596
}

597 598
ide_devset_get(acoustic, acoustic);

599
static int set_acoustic(ide_drive_t *drive, int arg)
Linus Torvalds's avatar
Linus Torvalds committed
600
{
601 602 603
	if (arg < 0 || arg > 254)
		return -EINVAL;

604 605 606
	ide_do_setfeature(drive,
		arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);

Linus Torvalds's avatar
Linus Torvalds committed
607
	drive->acoustic = arg;
608

Linus Torvalds's avatar
Linus Torvalds committed
609 610 611
	return 0;
}

612
ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
613

Linus Torvalds's avatar
Linus Torvalds committed
614 615 616 617 618 619
/*
 * drive->addressing:
 *	0: 28-bit
 *	1: 48-bit
 *	2: 48-bit capable doing 28-bit
 */
620
static int set_addressing(ide_drive_t *drive, int arg)
Linus Torvalds's avatar
Linus Torvalds committed
621
{
622 623 624
	if (arg < 0 || arg > 2)
		return -EINVAL;

625 626
	if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
	    ata_id_lba48_enabled(drive->id) == 0))
627
		return -EIO;
628

629 630 631
	if (arg == 2)
		arg = 0;

632 633 634 635
	if (arg)
		drive->dev_flags |= IDE_DFLAG_LBA48;
	else
		drive->dev_flags &= ~IDE_DFLAG_LBA48;
636

Linus Torvalds's avatar
Linus Torvalds committed
637 638 639
	return 0;
}

640 641 642 643
ide_ext_devset_rw(acoustic, acoustic);
ide_ext_devset_rw(address, addressing);
ide_ext_devset_rw(multcount, multcount);
ide_ext_devset_rw(wcache, wcache);
644

645
ide_ext_devset_rw_sync(nowerr, nowerr);
646

647 648 649 650 651 652
static int ide_disk_check(ide_drive_t *drive, const char *s)
{
	return 1;
}

static void ide_disk_setup(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
653
{
654
	struct ide_disk_obj *idkp = drive->driver_data;
655
	struct request_queue *q = drive->queue;
656
	ide_hwif_t *hwif = drive->hwif;
657 658
	u16 *id = drive->id;
	char *m = (char *)&id[ATA_ID_PROD];
Linus Torvalds's avatar
Linus Torvalds committed
659 660
	unsigned long long capacity;

661
	ide_proc_register_driver(drive, idkp->driver);
Linus Torvalds's avatar
Linus Torvalds committed
662

663
	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
Linus Torvalds's avatar
Linus Torvalds committed
664 665
		return;

666
	if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
Linus Torvalds's avatar
Linus Torvalds committed
667
		/*
668
		 * Removable disks (eg. SYQUEST); ignore 'WD' drives
Linus Torvalds's avatar
Linus Torvalds committed
669
		 */
670
		if (m[0] != 'W' || m[1] != 'D')
671
			drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
Linus Torvalds's avatar
Linus Torvalds committed
672 673
	}

674
	(void)set_addressing(drive, 1);
Linus Torvalds's avatar
Linus Torvalds committed
675

676
	if (drive->dev_flags & IDE_DFLAG_LBA48) {
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679 680 681
		int max_s = 2048;

		if (max_s > hwif->rqsize)
			max_s = hwif->rqsize;

682
		blk_queue_max_hw_sectors(q, max_s);
Linus Torvalds's avatar
Linus Torvalds committed
683 684
	}

685
	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
686
	       queue_max_sectors(q) / 2);
687

688
	if (ata_id_is_ssd(id)) {
689 690
		blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
		blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
691
	}
Linus Torvalds's avatar
Linus Torvalds committed
692 693

	/* calculate drive capacity, and select LBA if possible */
694
	ide_disk_get_capacity(drive);
Linus Torvalds's avatar
Linus Torvalds committed
695 696 697 698 699

	/*
	 * if possible, give fdisk access to more of the drive,
	 * by correcting bios_cyls:
	 */
700
	capacity = ide_gd_capacity(drive);
701

702
	if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
703
		if (ata_id_lba48_enabled(drive->id)) {
Linus Torvalds's avatar
Linus Torvalds committed
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
			/* compatibility */
			drive->bios_sect = 63;
			drive->bios_head = 255;
		}

		if (drive->bios_sect && drive->bios_head) {
			unsigned int cap0 = capacity; /* truncate to 32 bits */
			unsigned int cylsz, cyl;

			if (cap0 != capacity)
				drive->bios_cyl = 65535;
			else {
				cylsz = drive->bios_sect * drive->bios_head;
				cyl = cap0 / cylsz;
				if (cyl > 65535)
					cyl = 65535;
				if (cyl > drive->bios_cyl)
					drive->bios_cyl = cyl;
			}
		}
	}
	printk(KERN_INFO "%s: %llu sectors (%llu MB)",
			 drive->name, capacity, sectors_to_MB(capacity));

	/* Only print cache size when it was specified */
729 730
	if (id[ATA_ID_BUF_SIZE])
		printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
Linus Torvalds's avatar
Linus Torvalds committed
731

732 733
	printk(KERN_CONT ", CHS=%d/%d/%d\n",
			 drive->bios_cyl, drive->bios_head, drive->bios_sect);
Linus Torvalds's avatar
Linus Torvalds committed
734 735

	/* write cache enabled? */
736
	if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
737
		drive->dev_flags |= IDE_DFLAG_WCACHE;
Linus Torvalds's avatar
Linus Torvalds committed
738

739
	set_wcache(drive, 1);
740 741 742 743 744 745 746 747

	if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
	    (drive->head == 0 || drive->head > 16)) {
		printk(KERN_ERR "%s: invalid geometry: %d physical heads?\n",
			drive->name, drive->head);
		drive->dev_flags &= ~IDE_DFLAG_ATTACH;
	} else
		drive->dev_flags |= IDE_DFLAG_ATTACH;
Linus Torvalds's avatar
Linus Torvalds committed
748 749
}

750
static void ide_disk_flush(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
751
{
752 753
	if (ata_id_flush_enabled(drive->id) == 0 ||
	    (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
Linus Torvalds's avatar
Linus Torvalds committed
754 755 756 757 758 759
		return;

	if (do_idedisk_flushcache(drive))
		printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}

760 761 762 763 764 765 766
static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk)
{
	return 0;
}

static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk,
				 int on)
767
{
768
	struct ide_cmd cmd;
769 770 771 772
	int ret;

	if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
		return 0;
773

774 775
	memset(&cmd, 0, sizeof(cmd));
	cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
776 777
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
778

779
	ret = ide_no_data_taskfile(drive, &cmd);
780 781 782 783 784

	if (ret)
		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;

	return ret;
785
}
786 787

const struct ide_disk_ops ide_ata_disk_ops = {
788 789 790 791 792 793 794 795 796
	.check			= ide_disk_check,
	.unlock_native_capacity	= ide_disk_unlock_native_capacity,
	.get_capacity		= ide_disk_get_capacity,
	.setup			= ide_disk_setup,
	.flush			= ide_disk_flush,
	.init_media		= ide_disk_init_media,
	.set_doorlock		= ide_disk_set_doorlock,
	.do_request		= ide_do_rw_disk,
	.ioctl			= ide_disk_ioctl,
797
};