Blame view

drivers/ide/ide-taskfile.c 16.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
2
3
4
   *  Copyright (C) 2000-2002	   Michael Cornwell <cornwell@acm.org>
   *  Copyright (C) 2000-2002	   Andre Hedrick <andre@linux-ide.org>
   *  Copyright (C) 2001-2002	   Klaus Smolin
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   *					IBM Storage Technology Division
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
6
   *  Copyright (C) 2003-2004, 2007  Bartlomiej Zolnierkiewicz
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   *
   *  The big the bad and the ugly.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
651c29a17   Andrew Morton   [PATCH] ide: touc...
13
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/interrupt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
  #include <linux/delay.h>
  #include <linux/hdreg.h>
  #include <linux/ide.h>
55c16a700   Jens Axboe   IDE: sg chaining ...
20
  #include <linux/scatterlist.h>
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
21
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include <asm/io.h>
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  void ide_tf_readback(ide_drive_t *drive, struct ide_cmd *cmd)
  {
  	ide_hwif_t *hwif = drive->hwif;
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
  
  	/* Be sure we're looking at the low order bytes */
  	tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
  
  	tp_ops->tf_read(drive, &cmd->tf, cmd->valid.in.tf);
  
  	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
  		tp_ops->write_devctl(hwif, ATA_HOB | ATA_DEVCTL_OBS);
  
  		tp_ops->tf_read(drive, &cmd->hob, cmd->valid.in.hob);
  	}
  }
745483f10   Sergei Shtylyov   ide: simplify 'st...
40
  void ide_tf_dump(const char *s, struct ide_cmd *cmd)
9e42237f2   Bartlomiej Zolnierkiewicz   ide: add ide_tf_l...
41
  {
807e35d69   Bartlomiej Zolnierkiewicz   ide: use ide_tf_l...
42
43
44
45
  #ifdef DEBUG
  	printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
  		"lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x
  ",
745483f10   Sergei Shtylyov   ide: simplify 'st...
46
47
48
49
50
51
  	       s, cmd->tf.feature, cmd->tf.nsect,
  	       cmd->tf.lbal, cmd->tf.lbam, cmd->tf.lbah,
  	       cmd->tf.device, cmd->tf.command);
  	printk("%s: hob: nsect 0x%02x lbal 0x%02x lbam 0x%02x lbah 0x%02x
  ",
  	       s, cmd->hob.nsect, cmd->hob.lbal, cmd->hob.lbam, cmd->hob.lbah);
807e35d69   Bartlomiej Zolnierkiewicz   ide: use ide_tf_l...
52
  #endif
089c5c7e0   Bartlomiej Zolnierkiewicz   ide: factor out d...
53
  }
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
54
  int taskfile_lib_get_identify(ide_drive_t *drive, u8 *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
56
  	struct ide_cmd cmd;
650d841d9   Bartlomiej Zolnierkiewicz   ide: add struct i...
57

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
58
59
  	memset(&cmd, 0, sizeof(cmd));
  	cmd.tf.nsect = 0x01;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  	if (drive->media == ide_disk)
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
61
  		cmd.tf.command = ATA_CMD_ID_ATA;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  	else
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
63
  		cmd.tf.command = ATA_CMD_ID_ATAPI;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
64
65
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
66
  	cmd.protocol = ATA_PROT_PIO;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
67
68
  
  	return ide_raw_taskfile(drive, &cmd, buf, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  }
1192e528e   Bartlomiej Zolnierkiewicz   ide: use ->data_p...
70
  static ide_startstop_t task_no_data_intr(ide_drive_t *);
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
71
  static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct ide_cmd *);
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
72
  static ide_startstop_t task_pio_intr(ide_drive_t *);
1192e528e   Bartlomiej Zolnierkiewicz   ide: use ->data_p...
73

adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
74
  ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
76
  	ide_hwif_t *hwif = drive->hwif;
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
77
  	struct ide_cmd *cmd = &hwif->cmd;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
78
  	struct ide_taskfile *tf = &cmd->tf;
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
79
  	ide_handler_t *handler = NULL;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
80
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
f37afdaca   Bartlomiej Zolnierkiewicz   ide: constify str...
81
  	const struct ide_dma_ops *dma_ops = hwif->dma_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82

0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
83
84
85
  	if (orig_cmd->protocol == ATA_PROT_PIO &&
  	    (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) &&
  	    drive->mult_count == 0) {
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
86
87
  		pr_err("%s: multimode not set!
  ", drive->name);
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
88
  		return ide_stopped;
1edee60e9   Bartlomiej Zolnierkiewicz   ide: merge flagge...
89
  	}
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
90
91
  	if (orig_cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
  		orig_cmd->ftf_flags |= IDE_FTFLAG_SET_IN_FLAGS;
1edee60e9   Bartlomiej Zolnierkiewicz   ide: merge flagge...
92

adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
93
  	memcpy(cmd, orig_cmd, sizeof(*cmd));
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
94

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
95
  	if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
745483f10   Sergei Shtylyov   ide: simplify 'st...
96
  		ide_tf_dump(drive->name, cmd);
ecf3a31d2   Sergei Shtylyov   ide: turn set_irq...
97
  		tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
35218d1ca   Sergei Shtylyov   ide: move data re...
98
99
  
  		if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
745483f10   Sergei Shtylyov   ide: simplify 'st...
100
  			u8 data[2] = { cmd->tf.data, cmd->hob.data };
35218d1ca   Sergei Shtylyov   ide: move data re...
101
102
103
  
  			tp_ops->output_data(drive, cmd, data, 2);
  		}
4109d19af   Sergei Shtylyov   ide: move common ...
104
105
106
107
108
109
110
111
112
  
  		if (cmd->valid.out.tf & IDE_VALID_DEVICE) {
  			u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ?
  				  0xE0 : 0xEF;
  
  			if (!(cmd->ftf_flags & IDE_FTFLAG_FLAGGED))
  				cmd->tf.device &= HIHI;
  			cmd->tf.device |= drive->select;
  		}
c9ff9e7b6   Sergei Shtylyov   ide: refactor tf_...
113
114
  		tp_ops->tf_load(drive, &cmd->hob, cmd->valid.out.hob);
  		tp_ops->tf_load(drive, &cmd->tf,  cmd->valid.out.tf);
089c5c7e0   Bartlomiej Zolnierkiewicz   ide: factor out d...
115
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
117
118
119
120
121
122
123
  	switch (cmd->protocol) {
  	case ATA_PROT_PIO:
  		if (cmd->tf_flags & IDE_TFLAG_WRITE) {
  			tp_ops->exec_command(hwif, tf->command);
  			ndelay(400);	/* FIXME */
  			return pre_task_out_intr(drive, cmd);
  		}
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
124
  		handler = task_pio_intr;
1192e528e   Bartlomiej Zolnierkiewicz   ide: use ->data_p...
125
  		/* fall-through */
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
126
  	case ATA_PROT_NODATA:
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
127
128
  		if (handler == NULL)
  			handler = task_no_data_intr;
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
129
  		ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  		return ide_started;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
131
  	case ATA_PROT_DMA:
5ae5412d9   Bartlomiej Zolnierkiewicz   ide: add ide_dma_...
132
  		if (ide_dma_prepare(drive, cmd))
10d90157c   Bartlomiej Zolnierkiewicz   ide: convert do_r...
133
  			return ide_stopped;
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
134
  		hwif->expiry = dma_ops->dma_timer_expiry;
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
135
  		ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD);
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
136
  		dma_ops->dma_start(drive);
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
137
  	default:
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
138
  		return ide_started;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  }
f6e29e35c   Bartlomiej Zolnierkiewicz   ide-disk: use do_...
141
  EXPORT_SYMBOL_GPL(do_rw_taskfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
143
  static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
145
  	ide_hwif_t *hwif = drive->hwif;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
146
147
148
  	struct ide_cmd *cmd = &hwif->cmd;
  	struct ide_taskfile *tf = &cmd->tf;
  	int custom = (cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
149
  	int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  	u8 stat;
90d2c6bc6   Bartlomiej Zolnierkiewicz   ide: enable local...
151
  	local_irq_enable_in_hardirq();
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
152
153
  	while (1) {
  		stat = hwif->tp_ops->read_status(hwif);
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
154
  		if ((stat & ATA_BUSY) == 0 || retries-- == 0)
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
155
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  		udelay(10);
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
157
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158

d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
159
160
161
  	if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
  		if (custom && tf->command == ATA_CMD_SET_MULTI) {
  			drive->mult_req = drive->mult_count = 0;
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
162
  			drive->special_flags |= IDE_SFLAG_RECALIBRATE;
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
163
164
165
166
167
  			(void)ide_dump_status(drive, __func__, stat);
  			return ide_stopped;
  		} else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
  			if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
  				ide_set_handler(drive, &task_no_data_intr,
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
168
  						WAIT_WORSTCASE);
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
169
170
171
  				return ide_started;
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  		return ide_error(drive, "task_no_data_intr", stat);
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
173
  	}
c47137a99   Bartlomiej Zolnierkiewicz   ide: add ide_read...
174

e7fedc3ca   Bartlomiej Zolnierkiewicz   ide: use ide_comp...
175
  	if (custom && tf->command == ATA_CMD_SET_MULTI)
d6ff9f64e   Bartlomiej Zolnierkiewicz   ide: merge all TA...
176
  		drive->mult_count = drive->mult_req;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

d364c7f50   Bartlomiej Zolnierkiewicz   ide: use ide_comp...
178
179
  	if (custom == 0 || tf->command == ATA_CMD_IDLEIMMEDIATE ||
  	    tf->command == ATA_CMD_CHK_POWER) {
a09485df9   Bartlomiej Zolnierkiewicz   ide: move request...
180
  		struct request *rq = hwif->rq;
a09485df9   Bartlomiej Zolnierkiewicz   ide: move request...
181
182
183
  
  		if (blk_pm_request(rq))
  			ide_complete_pm_rq(drive, rq);
2230d90dd   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
184
185
  		else
  			ide_finish_cmd(drive, cmd, stat);
a09485df9   Bartlomiej Zolnierkiewicz   ide: move request...
186
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
  	return ide_stopped;
  }
da6f4c7f6   Adrian Bunk   ide: make wait_dr...
189
  static u8 wait_drive_not_busy(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
191
  	ide_hwif_t *hwif = drive->hwif;
b42fa1331   Masatake YAMATO   ide: never called...
192
  	int retries;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
  	u8 stat;
  
  	/*
f54feafa6   Bartlomiej Zolnierkiewicz   ide: increase tim...
196
197
  	 * Last sector was transfered, wait until device is ready.  This can
  	 * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  	 */
f54feafa6   Bartlomiej Zolnierkiewicz   ide: increase tim...
199
  	for (retries = 0; retries < 1000; retries++) {
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
200
  		stat = hwif->tp_ops->read_status(hwif);
c47137a99   Bartlomiej Zolnierkiewicz   ide: add ide_read...
201

3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
202
  		if (stat & ATA_BUSY)
b42fa1331   Masatake YAMATO   ide: never called...
203
204
205
206
  			udelay(10);
  		else
  			break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207

3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
208
  	if (stat & ATA_BUSY)
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
209
210
  		pr_err("%s: drive still BUSY!
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
  
  	return stat;
  }
a08915ba5   Bartlomiej Zolnierkiewicz   ide-cd: use scatt...
214
215
  void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
  		   unsigned int write, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
  {
  	ide_hwif_t *hwif = drive->hwif;
  	struct scatterlist *sg = hwif->sg_table;
b6308ee0c   Bartlomiej Zolnierkiewicz   ide: move command...
219
  	struct scatterlist *cursg = cmd->cursg;
7fa350b47   David S. Miller   ide: Fix annoying...
220
  	unsigned long uninitialized_var(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  	unsigned int offset;
  	u8 *buf;
b6308ee0c   Bartlomiej Zolnierkiewicz   ide: move command...
224
  	cursg = cmd->cursg;
7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
225
226
227
228
229
  	if (cursg == NULL)
  		cursg = cmd->cursg = sg;
  
  	while (len) {
  		unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs);
a90790521   Jean Delvare   IDE: Save a call ...
230
  		int page_is_high;
55c16a700   Jens Axboe   IDE: sg chaining ...
231

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
232
233
  		if (nr_bytes > PAGE_SIZE)
  			nr_bytes = PAGE_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
235
236
237
238
239
240
  		page = sg_page(cursg);
  		offset = cursg->offset + cmd->cursg_ofs;
  
  		/* get the current page and offset */
  		page = nth_page(page, (offset >> PAGE_SHIFT));
  		offset %= PAGE_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

a90790521   Jean Delvare   IDE: Save a call ...
242
243
  		page_is_high = PageHighMem(page);
  		if (page_is_high)
f2bc31673   Bartlomiej Zolnierkiewicz   ide: use PageHigh...
244
  			local_irq_save(flags);
7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
245
  		buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
247
248
  		cmd->nleft -= nr_bytes;
  		cmd->cursg_ofs += nr_bytes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
250
251
252
253
  		if (cmd->cursg_ofs == cursg->length) {
  			cursg = cmd->cursg = sg_next(cmd->cursg);
  			cmd->cursg_ofs = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
255
256
257
258
259
  		/* do the actual data transfer */
  		if (write)
  			hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes);
  		else
  			hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
261
  		kunmap_atomic(buf, KM_BIO_SRC_IRQ);
f2bc31673   Bartlomiej Zolnierkiewicz   ide: use PageHigh...
262

a90790521   Jean Delvare   IDE: Save a call ...
263
  		if (page_is_high)
f2bc31673   Bartlomiej Zolnierkiewicz   ide: use PageHigh...
264
  			local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
266
267
  		len -= nr_bytes;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  }
a08915ba5   Bartlomiej Zolnierkiewicz   ide-cd: use scatt...
269
  EXPORT_SYMBOL_GPL(ide_pio_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270

adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
271
272
  static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
  			      unsigned int write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  {
7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
274
  	unsigned int nr_bytes;
35cf2b94d   Tejun Heo   ide: fix ->io_32b...
275
  	u8 saved_io_32bit = drive->io_32bit;
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
276
277
  	if (cmd->tf_flags & IDE_TFLAG_FS)
  		cmd->rq->errors = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
279
  	if (cmd->tf_flags & IDE_TFLAG_IO_16BIT)
e3d9a73a8   Bartlomiej Zolnierkiewicz   ide: remove ->dat...
280
  		drive->io_32bit = 0;
35cf2b94d   Tejun Heo   ide: fix ->io_32b...
281

651c29a17   Andrew Morton   [PATCH] ide: touc...
282
  	touch_softlockup_watchdog();
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
283
  	if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
284
  		nr_bytes = min_t(unsigned, cmd->nleft, drive->mult_count << 9);
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
285
  	else
7a00798b1   Bartlomiej Zolnierkiewicz   ide: add support ...
286
287
288
  		nr_bytes = SECTOR_SIZE;
  
  	ide_pio_bytes(drive, cmd, write, nr_bytes);
35cf2b94d   Tejun Heo   ide: fix ->io_32b...
289
290
  
  	drive->io_32bit = saved_io_32bit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  }
041cea10a   Bartlomiej Zolnierkiewicz   ide: task_error()...
292
  static void ide_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  {
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
294
  	if (cmd->tf_flags & IDE_TFLAG_FS) {
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
295
  		int nr_bytes = cmd->nbytes - cmd->nleft;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296

0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
297
298
299
  		if (cmd->protocol == ATA_PROT_PIO &&
  		    ((cmd->tf_flags & IDE_TFLAG_WRITE) || cmd->nleft == 0)) {
  			if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
300
  				nr_bytes -= drive->mult_count << 9;
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
301
  			else
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
302
  				nr_bytes -= SECTOR_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  		}
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
304
305
  		if (nr_bytes > 0)
  			ide_complete_rq(drive, 0, nr_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  }
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
308
  void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  {
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
310
  	struct request *rq = drive->hwif->rq;
665d66e8f   Bartlomiej Zolnierkiewicz   ide: fix races in...
311
312
  	u8 err = ide_read_error(drive), nsect = cmd->tf.nsect;
  	u8 set_xfer = !!(cmd->tf_flags & IDE_TFLAG_SET_XFER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313

2230d90dd   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
314
  	ide_complete_cmd(drive, cmd, stat, err);
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
315
  	rq->errors = err;
665d66e8f   Bartlomiej Zolnierkiewicz   ide: fix races in...
316
317
318
319
320
  
  	if (err == 0 && set_xfer) {
  		ide_set_xfer_rate(drive, nsect);
  		ide_driveid_update(drive);
  	}
f974b196f   Bartlomiej Zolnierkiewicz   ide: pass number ...
321
  	ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
  }
  
  /*
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
325
   * Handler for command with PIO data phase.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
   */
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
327
  static ide_startstop_t task_pio_intr(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  {
  	ide_hwif_t *hwif = drive->hwif;
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
330
  	struct ide_cmd *cmd = &drive->hwif->cmd;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
331
  	u8 stat = hwif->tp_ops->read_status(hwif);
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
332
  	u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
334
335
336
  	if (write == 0) {
  		/* Error? */
  		if (stat & ATA_ERR)
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
337
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
339
  		/* Didn't want any data? Odd. */
151055ed8   Bartlomiej Zolnierkiewicz   ide: inline task_...
340
341
  		if ((stat & ATA_DRQ) == 0) {
  			/* Command all done? */
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
342
343
  			if (OK_STAT(stat, ATA_DRDY, ATA_BUSY))
  				goto out_end;
151055ed8   Bartlomiej Zolnierkiewicz   ide: inline task_...
344
345
  
  			/* Assume it was a spurious irq */
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
346
  			goto out_wait;
151055ed8   Bartlomiej Zolnierkiewicz   ide: inline task_...
347
  		}
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
348
349
  	} else {
  		if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
350
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
352
353
  		/* Deal with unexpected ATA data phase. */
  		if (((stat & ATA_DRQ) == 0) ^ (cmd->nleft == 0))
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
354
  			goto out_err;
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
355
  	}
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
356
357
  	if (write && cmd->nleft == 0)
  		goto out_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  
  	/* Still data left to transfer. */
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
360
  	ide_pio_datablock(drive, cmd, write);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361

901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
362
363
364
365
  	/* Are we done? Check status and finish transfer. */
  	if (write == 0 && cmd->nleft == 0) {
  		stat = wait_drive_not_busy(drive);
  		if (!OK_STAT(stat, 0, BAD_STAT))
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
366
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
368
369
370
  		goto out_end;
  	}
  out_wait:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  	/* Still data left to transfer. */
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
372
  	ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	return ide_started;
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
374
  out_end:
2230d90dd   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
375
376
377
  	if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
  		ide_finish_cmd(drive, cmd, stat);
  	else
9780e2dd8   Tejun Heo   ide: convert to r...
378
  		ide_complete_rq(drive, 0, blk_rq_sectors(cmd->rq) << 9);
0a1248c5a   Bartlomiej Zolnierkiewicz   ide: unify exit p...
379
380
  	return ide_stopped;
  out_err:
041cea10a   Bartlomiej Zolnierkiewicz   ide: task_error()...
381
382
  	ide_error_cmd(drive, cmd);
  	return ide_error(drive, __func__, stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  }
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
384
385
  static ide_startstop_t pre_task_out_intr(ide_drive_t *drive,
  					 struct ide_cmd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  {
  	ide_startstop_t startstop;
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
388
  	if (ide_wait_stat(&startstop, drive, ATA_DRQ,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  			  drive->bad_wstat, WAIT_DRQ)) {
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
390
391
  		pr_err("%s: no DRQ after issuing %sWRITE%s
  ", drive->name,
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
392
  			(cmd->tf_flags & IDE_TFLAG_MULTI_PIO) ? "MULT" : "",
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
393
  			(drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
  		return startstop;
  	}
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
396
  	if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  		local_irq_disable();
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
398
  	ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
901bd08a5   Bartlomiej Zolnierkiewicz   ide: merge task_{...
399

adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
400
  	ide_pio_datablock(drive, cmd, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
  
  	return ide_started;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
405
406
  int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
  		     u16 nsect)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  {
154ed280e   FUJITA Tomonori   ide-taskfile: con...
408
409
  	struct request *rq;
  	int error;
720fc22a7   Mikulas Patocka   ide: Fix IDE task...
410
  	int rw = !(cmd->tf_flags & IDE_TFLAG_WRITE) ? READ : WRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

720fc22a7   Mikulas Patocka   ide: Fix IDE task...
412
  	rq = blk_get_request(drive->queue, rw, __GFP_WAIT);
154ed280e   FUJITA Tomonori   ide-taskfile: con...
413
  	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
d868ca243   Tejun Heo   ide-taskfile: don...
414

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
418
419
420
  	/*
  	 * (ks) We transfer currently only whole sectors.
  	 * This is suffient for now.  But, it would be great,
  	 * if we would find a solution to transfer any size.
  	 * To support special commands like READ LONG.
  	 */
d868ca243   Tejun Heo   ide-taskfile: don...
421
422
423
424
425
426
  	if (nsect) {
  		error = blk_rq_map_kern(drive->queue, rq, buf,
  					nsect * SECTOR_SIZE, __GFP_WAIT);
  		if (error)
  			goto put_req;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
428
429
  	rq->special = cmd;
  	cmd->rq = rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430

154ed280e   FUJITA Tomonori   ide-taskfile: con...
431
  	error = blk_execute_rq(drive->queue, NULL, rq, 0);
154ed280e   FUJITA Tomonori   ide-taskfile: con...
432

d868ca243   Tejun Heo   ide-taskfile: don...
433
434
  put_req:
  	blk_put_request(rq);
154ed280e   FUJITA Tomonori   ide-taskfile: con...
435
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  EXPORT_SYMBOL(ide_raw_taskfile);
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
438
  int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd)
9a3c49be5   Bartlomiej Zolnierkiewicz   ide: add ide_no_d...
439
  {
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
440
  	cmd->protocol = ATA_PROT_NODATA;
9a3c49be5   Bartlomiej Zolnierkiewicz   ide: add ide_no_d...
441

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
442
  	return ide_raw_taskfile(drive, cmd, NULL, 0);
9a3c49be5   Bartlomiej Zolnierkiewicz   ide: add ide_no_d...
443
444
  }
  EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
26a5b0407   Bartlomiej Zolnierkiewicz   ide: add missing ...
445
  #ifdef CONFIG_IDE_TASK_IOCTL
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
446
  int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  {
  	ide_task_request_t	*req_task;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
449
  	struct ide_cmd		cmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  	u8 *outbuf		= NULL;
  	u8 *inbuf		= NULL;
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
452
  	u8 *data_buf		= NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
  	int err			= 0;
  	int tasksize		= sizeof(struct ide_task_request_s);
3a42bb223   Alan Cox   [PATCH] ide: add ...
455
456
  	unsigned int taskin	= 0;
  	unsigned int taskout	= 0;
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
457
  	u16 nsect		= 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  	char __user *buf = (char __user *)arg;
7d543d846   Julia Lawall   drivers/ide: Use ...
459
460
461
  	req_task = memdup_user(buf, tasksize);
  	if (IS_ERR(req_task))
  		return PTR_ERR(req_task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462

3a42bb223   Alan Cox   [PATCH] ide: add ...
463
464
  	taskout = req_task->out_size;
  	taskin  = req_task->in_size;
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
465

3a42bb223   Alan Cox   [PATCH] ide: add ...
466
467
468
469
  	if (taskin > 65536 || taskout > 65536) {
  		err = -EINVAL;
  		goto abort;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
  
  	if (taskout) {
  		int outtotal = tasksize;
f5e3c2faa   Deepak Saxena   [PATCH] ide: kmal...
473
  		outbuf = kzalloc(taskout, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
  		if (outbuf == NULL) {
  			err = -ENOMEM;
  			goto abort;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
482
483
484
485
  		if (copy_from_user(outbuf, buf + outtotal, taskout)) {
  			err = -EFAULT;
  			goto abort;
  		}
  	}
  
  	if (taskin) {
  		int intotal = tasksize + taskout;
f5e3c2faa   Deepak Saxena   [PATCH] ide: kmal...
486
  		inbuf = kzalloc(taskin, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
  		if (inbuf == NULL) {
  			err = -ENOMEM;
  			goto abort;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
  		if (copy_from_user(inbuf, buf + intotal, taskin)) {
  			err = -EFAULT;
  			goto abort;
  		}
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
496
  	memset(&cmd, 0, sizeof(cmd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

745483f10   Sergei Shtylyov   ide: simplify 'st...
498
499
  	memcpy(&cmd.hob, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
  	memcpy(&cmd.tf,  req_task->io_ports,  HDIO_DRIVE_TASK_HDR_SIZE);
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
500

60f85019c   Sergei Shtylyov   ide: replace IDE_...
501
502
503
  	cmd.valid.out.tf = IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_DEVICE | IDE_VALID_IN_TF;
  	cmd.tf_flags = IDE_TFLAG_IO_16BIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504

60f85019c   Sergei Shtylyov   ide: replace IDE_...
505
506
507
508
  	if (drive->dev_flags & IDE_DFLAG_LBA48) {
  		cmd.tf_flags |= IDE_TFLAG_LBA48;
  		cmd.valid.in.hob = IDE_VALID_IN_HOB;
  	}
a3bbb9d88   Bartlomiej Zolnierkiewicz   ide: remove unnec...
509

74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
510
  	if (req_task->out_flags.all) {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
511
  		cmd.ftf_flags |= IDE_FTFLAG_FLAGGED;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
512
513
  
  		if (req_task->out_flags.b.data)
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
514
  			cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
515
516
  
  		if (req_task->out_flags.b.nsector_hob)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
517
  			cmd.valid.out.hob |= IDE_VALID_NSECT;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
518
  		if (req_task->out_flags.b.sector_hob)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
519
  			cmd.valid.out.hob |= IDE_VALID_LBAL;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
520
  		if (req_task->out_flags.b.lcyl_hob)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
521
  			cmd.valid.out.hob |= IDE_VALID_LBAM;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
522
  		if (req_task->out_flags.b.hcyl_hob)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
523
  			cmd.valid.out.hob |= IDE_VALID_LBAH;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
524
525
  
  		if (req_task->out_flags.b.error_feature)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
526
  			cmd.valid.out.tf  |= IDE_VALID_FEATURE;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
527
  		if (req_task->out_flags.b.nsector)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
528
  			cmd.valid.out.tf  |= IDE_VALID_NSECT;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
529
  		if (req_task->out_flags.b.sector)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
530
  			cmd.valid.out.tf  |= IDE_VALID_LBAL;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
531
  		if (req_task->out_flags.b.lcyl)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
532
  			cmd.valid.out.tf  |= IDE_VALID_LBAM;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
533
  		if (req_task->out_flags.b.hcyl)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
534
  			cmd.valid.out.tf  |= IDE_VALID_LBAH;
a3bbb9d88   Bartlomiej Zolnierkiewicz   ide: remove unnec...
535
  	} else {
60f85019c   Sergei Shtylyov   ide: replace IDE_...
536
  		cmd.valid.out.tf |= IDE_VALID_OUT_TF;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
537
  		if (cmd.tf_flags & IDE_TFLAG_LBA48)
60f85019c   Sergei Shtylyov   ide: replace IDE_...
538
  			cmd.valid.out.hob |= IDE_VALID_OUT_HOB;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
539
  	}
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
540
  	if (req_task->in_flags.b.data)
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
541
  		cmd.ftf_flags |= IDE_FTFLAG_IN_DATA;
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
542

04d09b0e6   Bartlomiej Zolnierkiewicz   ide: set IDE_TFLA...
543
544
545
546
  	if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) {
  		/* fixup data phase if needed */
  		if (req_task->data_phase == TASKFILE_IN_DMAQ ||
  		    req_task->data_phase == TASKFILE_IN_DMA)
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
547
  			cmd.tf_flags |= IDE_TFLAG_WRITE;
04d09b0e6   Bartlomiej Zolnierkiewicz   ide: set IDE_TFLA...
548
  	}
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
549
550
551
  	cmd.protocol = ATA_PROT_DMA;
  
  	switch (req_task->data_phase) {
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  	case TASKFILE_MULTI_OUT:
  		if (!drive->mult_count) {
  			/* (hs): give up if multcount is not set */
  			pr_err("%s: %s Multimode Write multcount is not set
  ",
  				drive->name, __func__);
  			err = -EPERM;
  			goto abort;
  		}
  		cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
  		/* fall through */
  	case TASKFILE_OUT:
  		cmd.protocol = ATA_PROT_PIO;
  		/* fall through */
  	case TASKFILE_OUT_DMAQ:
  	case TASKFILE_OUT_DMA:
  		cmd.tf_flags |= IDE_TFLAG_WRITE;
  		nsect = taskout / SECTOR_SIZE;
  		data_buf = outbuf;
  		break;
  	case TASKFILE_MULTI_IN:
  		if (!drive->mult_count) {
  			/* (hs): give up if multcount is not set */
  			pr_err("%s: %s Multimode Read multcount is not set
  ",
  				drive->name, __func__);
  			err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  			goto abort;
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  		}
  		cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
  		/* fall through */
  	case TASKFILE_IN:
  		cmd.protocol = ATA_PROT_PIO;
  		/* fall through */
  	case TASKFILE_IN_DMAQ:
  	case TASKFILE_IN_DMA:
  		nsect = taskin / SECTOR_SIZE;
  		data_buf = inbuf;
  		break;
  	case TASKFILE_NO_DATA:
  		cmd.protocol = ATA_PROT_NODATA;
  		break;
  	default:
  		err = -EFAULT;
  		goto abort;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  	}
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
598
599
600
  	if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
  		nsect = 0;
  	else if (!nsect) {
745483f10   Sergei Shtylyov   ide: simplify 'st...
601
  		nsect = (cmd.hob.nsect << 8) | cmd.tf.nsect;
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
602
603
  
  		if (!nsect) {
2d5abcede   Jaswinder Singh Rajput   ide: ide-taskfile...
604
605
  			pr_err("%s: in/out command without data
  ",
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
606
607
608
609
610
  					drive->name);
  			err = -EFAULT;
  			goto abort;
  		}
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
611
  	err = ide_raw_taskfile(drive, &cmd, data_buf, nsect);
ac026ff25   Bartlomiej Zolnierkiewicz   ide: remove 'comm...
612

745483f10   Sergei Shtylyov   ide: simplify 'st...
613
614
  	memcpy(req_task->hob_ports, &cmd.hob, HDIO_DRIVE_HOB_HDR_SIZE - 2);
  	memcpy(req_task->io_ports,  &cmd.tf,  HDIO_DRIVE_TASK_HDR_SIZE);
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
615

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
616
  	if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) &&
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
617
618
  	    req_task->in_flags.all == 0) {
  		req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
619
  		if (drive->dev_flags & IDE_DFLAG_LBA48)
866e2ec9c   Bartlomiej Zolnierkiewicz   ide: remove 'tf_i...
620
621
  			req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  
  	if (copy_to_user(buf, req_task, tasksize)) {
  		err = -EFAULT;
  		goto abort;
  	}
  	if (taskout) {
  		int outtotal = tasksize;
  		if (copy_to_user(buf + outtotal, outbuf, taskout)) {
  			err = -EFAULT;
  			goto abort;
  		}
  	}
  	if (taskin) {
  		int intotal = tasksize + taskout;
  		if (copy_to_user(buf + intotal, inbuf, taskin)) {
  			err = -EFAULT;
  			goto abort;
  		}
  	}
  abort:
  	kfree(req_task);
6044ec888   Jesper Juhl   [PATCH] kfree cle...
643
644
  	kfree(outbuf);
  	kfree(inbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
  	return err;
  }
26a5b0407   Bartlomiej Zolnierkiewicz   ide: add missing ...
648
  #endif