Blame view

drivers/ide/ide-disk.c 19.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
2
3
4
   *  Copyright (C) 1994-1998	   Linus Torvalds & authors (see below)
   *  Copyright (C) 1998-2002	   Linux ATA Development
   *				      Andre Hedrick <andre@linux-ide.org>
ccd32e221   Alan Cox   ide: Switch to a ...
5
   *  Copyright (C) 2003		   Red Hat
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
6
   *  Copyright (C) 2003-2005, 2007  Bartlomiej Zolnierkiewicz
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
   */
  
  /*
   *  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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
23
24
25
26
  #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>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
27
  #include <linux/mutex.h>
2bfb646cd   Richard Purdie   [PATCH] LED: Add ...
28
  #include <linux/leds.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
35
  #include <linux/ide.h>
  
  #include <asm/byteorder.h>
  #include <asm/irq.h>
  #include <asm/uaccess.h>
  #include <asm/io.h>
  #include <asm/div64.h>
f87904898   Bartlomiej Zolnierkiewicz   ide-disk: move al...
36
  #include "ide-disk.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
38
  static const u8 ide_rw_cmds[] = {
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
39
40
41
42
43
44
45
46
47
48
49
50
  	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,
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
51
  };
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
52
  static void ide_tf_set_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 dma)
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
53
54
  {
  	u8 index, lba48, write;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
55
56
  	lba48 = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
  	write = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
57

0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
58
59
  	if (dma) {
  		cmd->protocol = ATA_PROT_DMA;
ba4b2e607   Bartlomiej Zolnierkiewicz   ide: remove dead ...
60
  		index = 8;
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
61
62
63
64
65
66
67
68
  	} else {
  		cmd->protocol = ATA_PROT_PIO;
  		if (drive->mult_count) {
  			cmd->tf_flags |= IDE_TFLAG_MULTI_PIO;
  			index = 0;
  		} else
  			index = 4;
  	}
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
69

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
70
  	cmd->tf.command = ide_rw_cmds[index + lba48 + write];
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
71
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
  /*
   * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
   * using LBA if supported, or CHS otherwise, to address sectors.
   */
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
76
77
  static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
  					sector_t block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
79
  	ide_hwif_t *hwif	= drive->hwif;
9780e2dd8   Tejun Heo   ide: convert to r...
80
  	u16 nsectors		= (u16)blk_rq_sectors(rq);
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
81
82
  	u8 lba48		= !!(drive->dev_flags & IDE_DFLAG_LBA48);
  	u8 dma			= !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
83
84
  	struct ide_cmd		cmd;
  	struct ide_taskfile	*tf = &cmd.tf;
f6e29e35c   Bartlomiej Zolnierkiewicz   ide-disk: use do_...
85
  	ide_startstop_t		rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

238e4f142   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
87
  	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
9780e2dd8   Tejun Heo   ide: convert to r...
88
  		if (block + blk_rq_sectors(rq) > 1ULL << 28)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
  			dma = 0;
  		else
  			lba48 = 0;
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
93
  	memset(&cmd, 0, sizeof(cmd));
60f85019c   Sergei Shtylyov   ide: replace IDE_...
94
95
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
2bd06b23e   Bartlomiej Zolnierkiewicz   ide-disk: use str...
96

d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
97
  	if (drive->dev_flags & IDE_DFLAG_LBA) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  		if (lba48) {
c2f8311d3   Michael Richardson   [PATCH] ide: cast...
99
100
101
  			pr_debug("%s: LBA=0x%012llx
  ", drive->name,
  					(unsigned long long)block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

790d12398   Bartlomiej Zolnierkiewicz   ide: remove ata_n...
103
  			tf->nsect  = nsectors & 0xff;
2bd06b23e   Bartlomiej Zolnierkiewicz   ide-disk: use str...
104
105
106
  			tf->lbal   = (u8) block;
  			tf->lbam   = (u8)(block >>  8);
  			tf->lbah   = (u8)(block >> 16);
745483f10   Sergei Shtylyov   ide: simplify 'st...
107
108
109
110
111
112
113
114
115
  			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);
  			}
6dd9b8376   Bartlomiej Zolnierkiewicz   ide: dump taskfil...
116

60f85019c   Sergei Shtylyov   ide: replace IDE_...
117
118
119
  			cmd.valid.out.hob = IDE_VALID_OUT_HOB;
  			cmd.valid.in.hob  = IDE_VALID_IN_HOB;
  			cmd.tf_flags |= IDE_TFLAG_LBA48;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  		} else {
790d12398   Bartlomiej Zolnierkiewicz   ide: remove ata_n...
121
  			tf->nsect  = nsectors & 0xff;
2bd06b23e   Bartlomiej Zolnierkiewicz   ide-disk: use str...
122
123
124
  			tf->lbal   = block;
  			tf->lbam   = block >>= 8;
  			tf->lbah   = block >>= 8;
745483f10   Sergei Shtylyov   ide: simplify 'st...
125
  			tf->device = ((block >> 8) & 0xf) | ATA_LBA;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  		}
  	} else {
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
128
  		unsigned int sect, head, cyl, track;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
  		track = (int)block / drive->sect;
  		sect  = (int)block % drive->sect + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
  		head  = track % drive->head;
  		cyl   = track / drive->head;
  
  		pr_debug("%s: CHS=%u/%u/%u
  ", drive->name, cyl, head, sect);
790d12398   Bartlomiej Zolnierkiewicz   ide: remove ata_n...
136
  		tf->nsect  = nsectors & 0xff;
2bd06b23e   Bartlomiej Zolnierkiewicz   ide-disk: use str...
137
138
139
140
  		tf->lbal   = sect;
  		tf->lbam   = cyl;
  		tf->lbah   = cyl >> 8;
  		tf->device = head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  	}
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
142
  	cmd.tf_flags |= IDE_TFLAG_FS;
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
143
  	if (rq_data_dir(rq))
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
144
  		cmd.tf_flags |= IDE_TFLAG_WRITE;
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
145

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
146
147
  	ide_tf_set_cmd(drive, &cmd, dma);
  	cmd.rq = rq;
ba76ae388   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
148

229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
149
  	if (dma == 0) {
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
150
  		ide_init_sg_cmd(&cmd, nsectors << 9);
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
151
152
  		ide_map_sg(drive, &cmd);
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
153
  	rc = do_rw_taskfile(drive, &cmd);
2bd06b23e   Bartlomiej Zolnierkiewicz   ide-disk: use str...
154

f6e29e35c   Bartlomiej Zolnierkiewicz   ide-disk: use do_...
155
  	if (rc == ide_stopped && dma) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  		/* fallback to PIO */
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
157
158
  		cmd.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
  		ide_tf_set_cmd(drive, &cmd, 0);
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
159
  		ide_init_sg_cmd(&cmd, nsectors << 9);
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
160
  		rc = do_rw_taskfile(drive, &cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  	}
f6e29e35c   Bartlomiej Zolnierkiewicz   ide-disk: use do_...
162
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
  }
  
  /*
   * 268435455  == 137439 MB or 28bit limit
   * 320173056  == 163929 MB or 48bit addressing
   * 1073741822 == 549756 MB or 48bit addressing fake drive
   */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
170
171
  static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
  				      sector_t block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
173
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
175
  	BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
33659ebba   Christoph Hellwig   block: remove wra...
176
  	BUG_ON(rq->cmd_type != REQ_TYPE_FS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

2bfb646cd   Richard Purdie   [PATCH] LED: Add ...
178
  	ledtrig_ide_activity();
9780e2dd8   Tejun Heo   ide: convert to r...
179
180
  	pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
9780e2dd8   Tejun Heo   ide: convert to r...
182
  		 (unsigned long long)block, blk_rq_sectors(rq),
c2f8311d3   Michael Richardson   [PATCH] ide: cast...
183
  		 (unsigned long)rq->buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
194
  
  	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.
   */
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
195
  static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
197
198
  	struct ide_cmd cmd;
  	struct ide_taskfile *tf = &cmd.tf;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
199
  	u64 addr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
201
  	memset(&cmd, 0, sizeof(cmd));
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
202
  	if (lba48)
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
203
  		tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
204
  	else
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
205
  		tf->command = ATA_CMD_READ_NATIVE_MAX;
650d841d9   Bartlomiej Zolnierkiewicz   ide: add struct i...
206
  	tf->device  = ATA_LBA;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
207

60f85019c   Sergei Shtylyov   ide: replace IDE_...
208
209
210
211
212
213
214
  	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;
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
215
216
  
  	ide_no_data_taskfile(drive, &cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
  
  	/* if OK, compute maximum address value */
47ab83485   Sergei Shtylyov   ide-disk: use ATA...
219
  	if (!(tf->status & ATA_ERR))
745483f10   Sergei Shtylyov   ide: simplify 'st...
220
  		addr = ide_get_lba_addr(&cmd, lba48) + 1;
650d841d9   Bartlomiej Zolnierkiewicz   ide: add struct i...
221

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
227
228
  	return addr;
  }
  
  /*
   * Sets maximum virtual LBA address of the drive.
   * Returns new maximum virtual LBA address (> 0) or 0 on failure.
   */
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
229
  static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
231
232
  	struct ide_cmd cmd;
  	struct ide_taskfile *tf = &cmd.tf;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
233
  	u64 addr_set = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
  
  	addr_req--;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
236
237
  
  	memset(&cmd, 0, sizeof(cmd));
650d841d9   Bartlomiej Zolnierkiewicz   ide: add struct i...
238
239
240
  	tf->lbal     = (addr_req >>  0) & 0xff;
  	tf->lbam     = (addr_req >>= 8) & 0xff;
  	tf->lbah     = (addr_req >>= 8) & 0xff;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
241
  	if (lba48) {
745483f10   Sergei Shtylyov   ide: simplify 'st...
242
243
244
  		cmd.hob.lbal = (addr_req >>= 8) & 0xff;
  		cmd.hob.lbam = (addr_req >>= 8) & 0xff;
  		cmd.hob.lbah = (addr_req >>= 8) & 0xff;
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
245
  		tf->command  = ATA_CMD_SET_MAX_EXT;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
246
247
  	} else {
  		tf->device   = (addr_req >>= 8) & 0x0f;
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
248
  		tf->command  = ATA_CMD_SET_MAX;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
249
250
  	}
  	tf->device |= ATA_LBA;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
251

60f85019c   Sergei Shtylyov   ide: replace IDE_...
252
253
254
255
256
257
258
  	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;
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
259
260
  
  	ide_no_data_taskfile(drive, &cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  	/* if OK, compute maximum address value */
47ab83485   Sergei Shtylyov   ide-disk: use ATA...
262
  	if (!(tf->status & ATA_ERR))
745483f10   Sergei Shtylyov   ide: simplify 'st...
263
  		addr_set = ide_get_lba_addr(&cmd, lba48) + 1;
650d841d9   Bartlomiej Zolnierkiewicz   ide: add struct i...
264

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
272
273
274
275
  	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;
  }
  
  /*
b0244a004   Bartlomiej Zolnierkiewicz   ide-disk: workaro...
276
277
278
279
280
   * 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 },
7062cdc5e   Jorge Juan Chico   ide: ST320413A ha...
281
  	{ "ST320413A",	NULL },
b152fcd34   Mikko Rapeli   ide/libata: ST310...
282
  	{ "ST310211A",	NULL },
b0244a004   Bartlomiej Zolnierkiewicz   ide-disk: workaro...
283
284
  	{ NULL,		NULL }
  };
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
285
  static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  {
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
287
  	u64 capacity, set_max;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  
  	capacity = drive->capacity64;
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
290
  	set_max  = idedisk_read_native_max_address(drive, lba48);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291

b0244a004   Bartlomiej Zolnierkiewicz   ide-disk: workaro...
292
293
294
295
296
297
298
299
  	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--;
  	}
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  	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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
  	if (set_max <= capacity)
  		return;
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
321
  	drive->probed_capacity = set_max;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
327
328
329
330
  	printk(KERN_INFO "%s: Host Protected Area detected.
  "
  			 "\tcurrent capacity is %llu sectors (%llu MB)
  "
  			 "\tnative  capacity is %llu sectors (%llu MB)
  ",
  			 drive->name,
  			 capacity, sectors_to_MB(capacity),
  			 set_max, sectors_to_MB(set_max));
075affcbe   Bartlomiej Zolnierkiewicz   ide: preserve Hos...
331
332
  	if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0)
  		return;
7a3b7512d   Bartlomiej Zolnierkiewicz   ide-disk: merge L...
333

e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
334
335
  	set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48);
  	if (set_max)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
  		printk(KERN_INFO "%s: Host Protected Area disabled.
  ",
  				 drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
340
  static int ide_disk_get_capacity(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
342
  	u16 *id = drive->id;
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
343
  	int lba;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344

942dcd85b   Bartlomiej Zolnierkiewicz   ide: idedisk_supp...
345
  	if (ata_id_lba48_enabled(id)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		/* drive speaks 48-bit LBA */
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
347
  		lba = 1;
48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
348
  		drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
a02227c97   Bartlomiej Zolnierkiewicz   ide: lba_capacity...
349
  	} else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  		/* drive speaks 28-bit LBA */
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
351
  		lba = 1;
48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
352
  		drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
  	} else {
  		/* drive speaks boring old 28-bit CHS */
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
355
  		lba = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
  		drive->capacity64 = drive->cyl * drive->head * drive->sect;
  	}
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
358

e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
359
  	drive->probed_capacity = drive->capacity64;
d1d76714e   Bartlomiej Zolnierkiewicz   ide: fix HDIO_DRI...
360
361
362
363
364
365
366
367
368
369
  	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);
  	}
0a70c7f67   Bartlomiej Zolnierkiewicz   ide-disk: fix IDE...
370
371
372
373
374
375
376
377
378
  
  	/* 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)
  ",
  		       drive->name, (unsigned long long)drive->capacity64,
  		       sectors_to_MB(drive->capacity64));
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
379
  		drive->probed_capacity = drive->capacity64 = 1ULL << 28;
0a70c7f67   Bartlomiej Zolnierkiewicz   ide-disk: fix IDE...
380
381
382
383
384
385
386
387
388
389
390
391
  	}
  
  	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
  ", drive->name, 1 << 28);
  		} else
  			drive->dev_flags &= ~IDE_DFLAG_LBA48;
  	}
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
392
393
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  }
c3e33e043   Tejun Heo   block,ide: simpli...
395
  static void ide_disk_unlock_native_capacity(ide_drive_t *drive)
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
396
  {
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
397
398
399
400
401
  	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)
c3e33e043   Tejun Heo   block,ide: simpli...
402
  		return;
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
403
404
405
406
407
  
  	/*
  	 * according to the spec the SET MAX ADDRESS command shall be
  	 * immediately preceded by a READ NATIVE MAX ADDRESS command
  	 */
c3e33e043   Tejun Heo   block,ide: simpli...
408
409
410
411
412
  	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 */
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
413
  }
afc230681   FUJITA Tomonori   ide: stop using q...
414
  static int idedisk_prep_fn(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  {
  	ide_drive_t *drive = q->queuedata;
afc230681   FUJITA Tomonori   ide: stop using q...
417
418
419
420
  	struct ide_cmd *cmd;
  
  	if (!(rq->cmd_flags & REQ_FLUSH))
  		return BLKPREP_OK;
2c8fc8676   Borislav Petkov   ide-disk: Fix req...
421
422
423
424
425
426
  	if (rq->special) {
  		cmd = rq->special;
  		memset(cmd, 0, sizeof(*cmd));
  	} else {
  		cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427

395d8ef5b   Bartlomiej Zolnierkiewicz   ide-disk: fix flu...
428
  	/* FIXME: map struct ide_taskfile on rq->cmd[] */
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
429
  	BUG_ON(cmd == NULL);
395d8ef5b   Bartlomiej Zolnierkiewicz   ide-disk: fix flu...
430

ff2779b56   Bartlomiej Zolnierkiewicz   ide: ide_id_has_f...
431
  	if (ata_id_flush_ext_enabled(drive->id) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  	    (drive->capacity64 >= (1UL << 28)))
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
433
  		cmd->tf.command = ATA_CMD_FLUSH_EXT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  	else
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
435
  		cmd->tf.command = ATA_CMD_FLUSH;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
436
437
  	cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd->tf_flags = IDE_TFLAG_DYN;
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
438
  	cmd->protocol = ATA_PROT_NODATA;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

813a0eb23   Bartlomiej Zolnierkiewicz   ide: switch idedi...
440
  	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
441
  	rq->special = cmd;
bc146d23d   Maxime Bizon   ide: fix memory l...
442
  	cmd->rq = rq;
afc230681   FUJITA Tomonori   ide: stop using q...
443
444
  
  	return BLKPREP_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  }
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
446
  ide_devset_get(multcount, mult_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
  /*
   * 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)
  {
dd47087bc   FUJITA Tomonori   ide-disk: convert...
453
454
  	struct request *rq;
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
456
  	if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
1497943ee   Bartlomiej Zolnierkiewicz   ide: split off io...
457
  		return -EINVAL;
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
458
  	if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  		return -EBUSY;
852738f39   Bartlomiej Zolnierkiewicz   ide: convert "emp...
460

dd47087bc   FUJITA Tomonori   ide-disk: convert...
461
462
  	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
  	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
852738f39   Bartlomiej Zolnierkiewicz   ide: convert "emp...
463

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  	drive->mult_req = arg;
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
465
  	drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
dd47087bc   FUJITA Tomonori   ide-disk: convert...
466
467
  	error = blk_execute_rq(drive->queue, NULL, rq, 0);
  	blk_put_request(rq);
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
468

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
  	return (drive->mult_count == arg) ? 0 : -EIO;
  }
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
471
  ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
472

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
  static int set_nowerr(ide_drive_t *drive, int arg)
  {
1497943ee   Bartlomiej Zolnierkiewicz   ide: split off io...
475
476
  	if (arg < 0 || arg > 1)
  		return -EINVAL;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
477
478
479
480
  	if (arg)
  		drive->dev_flags |= IDE_DFLAG_NOWERR;
  	else
  		drive->dev_flags &= ~IDE_DFLAG_NOWERR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
482

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
  	return 0;
  }
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
485
486
  static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
487
  	struct ide_cmd cmd;
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
488

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
489
490
491
492
  	memset(&cmd, 0, sizeof(cmd));
  	cmd.tf.feature = feature;
  	cmd.tf.nsect   = nsect;
  	cmd.tf.command = ATA_CMD_SET_FEATURES;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
493
494
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
495

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
496
  	return ide_no_data_taskfile(drive, &cmd);
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
497
  }
4913efe45   Tejun Heo   block: deprecate ...
498
  static void update_flush(ide_drive_t *drive)
3e087b575   Tejun Heo   [BLOCK] update ID...
499
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
500
  	u16 *id = drive->id;
4913efe45   Tejun Heo   block: deprecate ...
501
  	unsigned flush = 0;
3e087b575   Tejun Heo   [BLOCK] update ID...
502

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
503
  	if (drive->dev_flags & IDE_DFLAG_WCACHE) {
3e087b575   Tejun Heo   [BLOCK] update ID...
504
505
506
507
508
509
510
511
512
513
  		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.
  		 */
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
514
  		capacity = ide_gd_capacity(drive);
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
515
516
517
518
  		barrier = ata_id_flush_enabled(id) &&
  			(drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
  			((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
  			 capacity <= (1ULL << 28) ||
ff2779b56   Bartlomiej Zolnierkiewicz   ide: ide_id_has_f...
519
  			 ata_id_flush_ext_enabled(id));
3e087b575   Tejun Heo   [BLOCK] update ID...
520
521
522
  
  		printk(KERN_INFO "%s: cache flushes %ssupported
  ",
f7ad836c4   Jean Delvare   [PATCH] ide-disk:...
523
  		       drive->name, barrier ? "" : "not ");
3e087b575   Tejun Heo   [BLOCK] update ID...
524
525
  
  		if (barrier) {
4913efe45   Tejun Heo   block: deprecate ...
526
  			flush = REQ_FLUSH;
afc230681   FUJITA Tomonori   ide: stop using q...
527
  			blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
3e087b575   Tejun Heo   [BLOCK] update ID...
528
  		}
4913efe45   Tejun Heo   block: deprecate ...
529
  	}
3e087b575   Tejun Heo   [BLOCK] update ID...
530

4913efe45   Tejun Heo   block: deprecate ...
531
  	blk_queue_flush(drive->queue, flush);
3e087b575   Tejun Heo   [BLOCK] update ID...
532
  }
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
533
  ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
534
535
  
  static int set_wcache(ide_drive_t *drive, int arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  {
3e087b575   Tejun Heo   [BLOCK] update ID...
537
  	int err = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538

1497943ee   Bartlomiej Zolnierkiewicz   ide: split off io...
539
540
  	if (arg < 0 || arg > 1)
  		return -EINVAL;
4b58f17d7   Bartlomiej Zolnierkiewicz   ide: ide_id_has_f...
541
  	if (ata_id_flush_enabled(drive->id)) {
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
542
543
  		err = ide_do_setfeature(drive,
  			arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
544
545
546
547
548
549
  		if (err == 0) {
  			if (arg)
  				drive->dev_flags |= IDE_DFLAG_WCACHE;
  			else
  				drive->dev_flags &= ~IDE_DFLAG_WCACHE;
  		}
3e087b575   Tejun Heo   [BLOCK] update ID...
550
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551

4913efe45   Tejun Heo   block: deprecate ...
552
  	update_flush(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553

3e087b575   Tejun Heo   [BLOCK] update ID...
554
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  }
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
556
  static int do_idedisk_flushcache(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
558
  	struct ide_cmd cmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
560
  	memset(&cmd, 0, sizeof(cmd));
ff2779b56   Bartlomiej Zolnierkiewicz   ide: ide_id_has_f...
561
  	if (ata_id_flush_ext_enabled(drive->id))
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
562
  		cmd.tf.command = ATA_CMD_FLUSH_EXT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
  	else
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
564
  		cmd.tf.command = ATA_CMD_FLUSH;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
565
566
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
567
568
  
  	return ide_no_data_taskfile(drive, &cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  }
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
570
  ide_devset_get(acoustic, acoustic);
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
571
  static int set_acoustic(ide_drive_t *drive, int arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  {
1497943ee   Bartlomiej Zolnierkiewicz   ide: split off io...
573
574
  	if (arg < 0 || arg > 254)
  		return -EINVAL;
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
575
576
  	ide_do_setfeature(drive,
  		arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  	drive->acoustic = arg;
be3c096eb   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
578

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
  	return 0;
  }
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
581
  ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
582

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
586
587
588
  /*
   * drive->addressing:
   *	0: 28-bit
   *	1: 48-bit
   *	2: 48-bit capable doing 28-bit
   */
aa7687738   Bartlomiej Zolnierkiewicz   ide: add ide_sett...
589
  static int set_addressing(ide_drive_t *drive, int arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  {
1497943ee   Bartlomiej Zolnierkiewicz   ide: split off io...
591
592
  	if (arg < 0 || arg > 2)
  		return -EINVAL;
35c137531   Bartlomiej Zolnierkiewicz   ide-disk: set_add...
593
594
  	if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
  	    ata_id_lba48_enabled(drive->id) == 0))
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
595
  		return -EIO;
942dcd85b   Bartlomiej Zolnierkiewicz   ide: idedisk_supp...
596

35c137531   Bartlomiej Zolnierkiewicz   ide-disk: set_add...
597
598
  	if (arg == 2)
  		arg = 0;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
599
600
601
602
  	if (arg)
  		drive->dev_flags |= IDE_DFLAG_LBA48;
  	else
  		drive->dev_flags &= ~IDE_DFLAG_LBA48;
942dcd85b   Bartlomiej Zolnierkiewicz   ide: idedisk_supp...
603

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
  	return 0;
  }
f87904898   Bartlomiej Zolnierkiewicz   ide-disk: move al...
606
607
608
609
  ide_ext_devset_rw(acoustic, acoustic);
  ide_ext_devset_rw(address, addressing);
  ide_ext_devset_rw(multcount, multcount);
  ide_ext_devset_rw(wcache, wcache);
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
610

f87904898   Bartlomiej Zolnierkiewicz   ide-disk: move al...
611
  ide_ext_devset_rw_sync(nowerr, nowerr);
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
612

806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
613
614
615
616
617
618
  static int ide_disk_check(ide_drive_t *drive, const char *s)
  {
  	return 1;
  }
  
  static void ide_disk_setup(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  {
1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
620
  	struct ide_disk_obj *idkp = drive->driver_data;
c77380d45   Bartlomiej Zolnierkiewicz   ide-disk: set non...
621
  	struct request_queue *q = drive->queue;
238e4f142   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
622
  	ide_hwif_t *hwif = drive->hwif;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
623
624
  	u16 *id = drive->id;
  	char *m = (char *)&id[ATA_ID_PROD];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  	unsigned long long capacity;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
627
  	ide_proc_register_driver(drive, idkp->driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
629
  	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  		return;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
631
  	if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  		/*
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
633
  		 * Removable disks (eg. SYQUEST); ignore 'WD' drives
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  		 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
635
  		if (m[0] != 'W' || m[1] != 'D')
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
636
  			drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  	}
aa7687738   Bartlomiej Zolnierkiewicz   ide: add ide_sett...
638
  	(void)set_addressing(drive, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
640
  	if (drive->dev_flags & IDE_DFLAG_LBA48) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
642
643
644
  		int max_s = 2048;
  
  		if (max_s > hwif->rqsize)
  			max_s = hwif->rqsize;
086fa5ff0   Martin K. Petersen   block: Rename blk...
645
  		blk_queue_max_hw_sectors(q, max_s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  	}
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
647
648
  	printk(KERN_INFO "%s: max request size: %dKiB
  ", drive->name,
3b77f777b   Martin K. Petersen   ide-disk: fix mis...
649
  	       queue_max_sectors(q) / 2);
c77380d45   Bartlomiej Zolnierkiewicz   ide-disk: set non...
650

655772cc7   Bartlomiej Zolnierkiewicz   ide: can't use SS...
651
  	if (ata_id_is_ssd(id))
c77380d45   Bartlomiej Zolnierkiewicz   ide-disk: set non...
652
  		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
  
  	/* calculate drive capacity, and select LBA if possible */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
655
  	ide_disk_get_capacity(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
  	/*
  	 * if possible, give fdisk access to more of the drive,
  	 * by correcting bios_cyls:
  	 */
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
661
  	capacity = ide_gd_capacity(drive);
984165494   Bartlomiej Zolnierkiewicz   ide-disk: fix iss...
662

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
663
  	if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
942dcd85b   Bartlomiej Zolnierkiewicz   ide: idedisk_supp...
664
  		if (ata_id_lba48_enabled(drive->id)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  			/* 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 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
690
691
  	if (id[ATA_ID_BUF_SIZE])
  		printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692

3ab7efe8e   Bartlomiej Zolnierkiewicz   ide: DMA reportin...
693
694
695
  	printk(KERN_CONT ", CHS=%d/%d/%d
  ",
  			 drive->bios_cyl, drive->bios_head, drive->bios_sect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  	/* write cache enabled? */
8a089c667   Bartlomiej Zolnierkiewicz   ide-disk: use ata...
698
  	if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
699
  		drive->dev_flags |= IDE_DFLAG_WCACHE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700

8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
701
  	set_wcache(drive, 1);
ae9f9f073   Bartlomiej Zolnierkiewicz   ide-{disk,floppy}...
702
703
704
705
706
707
708
709
710
  
  	if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
  	    (drive->head == 0 || drive->head > 16)) {
  		printk(KERN_ERR "%s: invalid geometry: %d physical heads?
  ",
  			drive->name, drive->head);
  		drive->dev_flags &= ~IDE_DFLAG_ATTACH;
  	} else
  		drive->dev_flags |= IDE_DFLAG_ATTACH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
712
  static void ide_disk_flush(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
  {
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
714
715
  	if (ata_id_flush_enabled(drive->id) == 0 ||
  	    (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
718
719
720
721
  		return;
  
  	if (do_idedisk_flushcache(drive))
  		printk(KERN_INFO "%s: wcache flush failed!
  ", drive->name);
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
722
723
724
725
726
727
728
  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)
29ec683f0   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
729
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
730
  	struct ide_cmd cmd;
81ee1bb51   Bartlomiej Zolnierkiewicz   ide-disk: move ID...
731
732
733
734
  	int ret;
  
  	if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
  		return 0;
29ec683f0   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
735

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
736
737
  	memset(&cmd, 0, sizeof(cmd));
  	cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
738
739
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
29ec683f0   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
740

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
741
  	ret = ide_no_data_taskfile(drive, &cmd);
81ee1bb51   Bartlomiej Zolnierkiewicz   ide-disk: move ID...
742
743
744
745
746
  
  	if (ret)
  		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
  
  	return ret;
29ec683f0   Bartlomiej Zolnierkiewicz   ide-disk: add ide...
747
  }
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
748
749
  
  const struct ide_disk_ops ide_ata_disk_ops = {
c3e33e043   Tejun Heo   block,ide: simpli...
750
751
752
753
754
755
756
757
758
  	.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,
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
759
  };