| Linux kernel & device driver programming |
| [ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] |
1 /* 1 /*
2 * Copyright (C) 2000-2002 Michael Cor !! 2 * linux/drivers/ide/ide-taskfile.c Version 0.38 March 05, 2003
3 * Copyright (C) 2000-2002 Andre Hedri !! 3 *
4 * Copyright (C) 2001-2002 Klaus Smoli !! 4 * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org>
>> 5 * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
>> 6 * Copyright (C) 2001-2002 Klaus Smolin
5 * IBM St 7 * IBM Storage Technology Division
6 * Copyright (C) 2003-2004, 2007 Bartlomiej !! 8 * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz
7 * 9 *
8 * The big the bad and the ugly. 10 * The big the bad and the ugly.
>> 11 *
>> 12 * Problems to be fixed because of BH interface or the lack therefore.
>> 13 *
>> 14 * Fill me in stupid !!!
>> 15 *
>> 16 * HOST:
>> 17 * General refers to the Controller and Driver "pair".
>> 18 * DATA HANDLER:
>> 19 * Under the context of Linux it generally refers to an interrupt handler.
>> 20 * However, it correctly describes the 'HOST'
>> 21 * DATA BLOCK:
>> 22 * The amount of data needed to be transfered as predefined in the
>> 23 * setup of the device.
>> 24 * STORAGE ATOMIC:
>> 25 * The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as
>> 26 * small as a single sector or as large as the entire command block
>> 27 * request.
9 */ 28 */
10 29
>> 30 #include <linux/config.h>
11 #include <linux/module.h> 31 #include <linux/module.h>
12 #include <linux/types.h> 32 #include <linux/types.h>
13 #include <linux/string.h> 33 #include <linux/string.h>
14 #include <linux/kernel.h> 34 #include <linux/kernel.h>
15 #include <linux/timer.h> 35 #include <linux/timer.h>
16 #include <linux/mm.h> 36 #include <linux/mm.h>
17 #include <linux/sched.h> <<
18 #include <linux/interrupt.h> 37 #include <linux/interrupt.h>
19 #include <linux/major.h> 38 #include <linux/major.h>
20 #include <linux/errno.h> 39 #include <linux/errno.h>
21 #include <linux/genhd.h> 40 #include <linux/genhd.h>
22 #include <linux/blkpg.h> 41 #include <linux/blkpg.h>
23 #include <linux/slab.h> 42 #include <linux/slab.h>
24 #include <linux/pci.h> 43 #include <linux/pci.h>
25 #include <linux/delay.h> 44 #include <linux/delay.h>
26 #include <linux/hdreg.h> 45 #include <linux/hdreg.h>
27 #include <linux/ide.h> 46 #include <linux/ide.h>
28 #include <linux/bitops.h> 47 #include <linux/bitops.h>
29 #include <linux/scatterlist.h> <<
30 48
31 #include <asm/byteorder.h> 49 #include <asm/byteorder.h>
32 #include <asm/irq.h> 50 #include <asm/irq.h>
33 #include <asm/uaccess.h> 51 #include <asm/uaccess.h>
34 #include <asm/io.h> 52 #include <asm/io.h>
35 53
36 void ide_tf_load(ide_drive_t *drive, ide_task_ !! 54 #define DEBUG_TASKFILE 0 /* unset when fixed */
37 { <<
38 ide_hwif_t *hwif = drive->hwif; <<
39 struct ide_taskfile *tf = &task->tf; <<
40 u8 HIHI = (task->tf_flags & IDE_TFLAG_ <<
41 <<
42 if (task->tf_flags & IDE_TFLAG_FLAGGED <<
43 HIHI = 0xFF; <<
44 55
45 #ifdef DEBUG !! 56 static void ata_bswap_data (void *buffer, int wcount)
46 printk("%s: tf: feat 0x%02x nsect 0x%0 !! 57 {
47 "lbam 0x%02x lbah 0x%02x dev 0 !! 58 u16 *p = buffer;
48 drive->name, tf->feature, tf-> <<
49 tf->lbam, tf->lbah, tf->device <<
50 printk("%s: hob: nsect 0x%02x lbal 0x% <<
51 "lbam 0x%02x lbah 0x%02x\n", <<
52 drive->name, tf->hob_nsect, tf <<
53 tf->hob_lbam, tf->hob_lbah); <<
54 #endif <<
55 <<
56 ide_set_irq(drive, 1); <<
57 <<
58 if ((task->tf_flags & IDE_TFLAG_NO_SEL <<
59 SELECT_MASK(drive, 0); <<
60 59
61 if (task->tf_flags & IDE_TFLAG_OUT_DAT !! 60 while (wcount--) {
62 hwif->OUTW((tf->hob_data << 8) !! 61 *p = *p << 8 | *p >> 8; p++;
>> 62 *p = *p << 8 | *p >> 8; p++;
>> 63 }
>> 64 }
63 65
64 if (task->tf_flags & IDE_TFLAG_OUT_HOB !! 66 static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
65 hwif->OUTB(tf->hob_feature, ID !! 67 {
66 if (task->tf_flags & IDE_TFLAG_OUT_HOB !! 68 HWIF(drive)->ata_input_data(drive, buffer, wcount);
67 hwif->OUTB(tf->hob_nsect, IDE_ !! 69 if (drive->bswap)
68 if (task->tf_flags & IDE_TFLAG_OUT_HOB !! 70 ata_bswap_data(buffer, wcount);
69 hwif->OUTB(tf->hob_lbal, IDE_S !! 71 }
70 if (task->tf_flags & IDE_TFLAG_OUT_HOB <<
71 hwif->OUTB(tf->hob_lbam, IDE_L <<
72 if (task->tf_flags & IDE_TFLAG_OUT_HOB <<
73 hwif->OUTB(tf->hob_lbah, IDE_H <<
74 <<
75 if (task->tf_flags & IDE_TFLAG_OUT_FEA <<
76 hwif->OUTB(tf->feature, IDE_FE <<
77 if (task->tf_flags & IDE_TFLAG_OUT_NSE <<
78 hwif->OUTB(tf->nsect, IDE_NSEC <<
79 if (task->tf_flags & IDE_TFLAG_OUT_LBA <<
80 hwif->OUTB(tf->lbal, IDE_SECTO <<
81 if (task->tf_flags & IDE_TFLAG_OUT_LBA <<
82 hwif->OUTB(tf->lbam, IDE_LCYL_ <<
83 if (task->tf_flags & IDE_TFLAG_OUT_LBA <<
84 hwif->OUTB(tf->lbah, IDE_HCYL_ <<
85 72
86 if (task->tf_flags & IDE_TFLAG_OUT_DEV !! 73 static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
87 hwif->OUTB((tf->device & HIHI) !! 74 {
>> 75 if (drive->bswap) {
>> 76 ata_bswap_data(buffer, wcount);
>> 77 HWIF(drive)->ata_output_data(drive, buffer, wcount);
>> 78 ata_bswap_data(buffer, wcount);
>> 79 } else {
>> 80 HWIF(drive)->ata_output_data(drive, buffer, wcount);
>> 81 }
88 } 82 }
89 83
90 int taskfile_lib_get_identify (ide_drive_t *dr 84 int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
91 { 85 {
92 ide_task_t args; 86 ide_task_t args;
93 <<
94 memset(&args, 0, sizeof(ide_task_t)); 87 memset(&args, 0, sizeof(ide_task_t));
95 args.tf.nsect = 0x01; !! 88 args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
96 if (drive->media == ide_disk) 89 if (drive->media == ide_disk)
97 args.tf.command = WIN_IDENTIFY !! 90 args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY;
98 else 91 else
99 args.tf.command = WIN_PIDENTIF !! 92 args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY;
100 args.tf_flags = IDE_TFLAG_TF | IDE_T !! 93 args.command_type = IDE_DRIVE_TASK_IN;
101 args.data_phase = TASKFILE_IN; !! 94 args.data_phase = TASKFILE_IN;
102 return ide_raw_taskfile(drive, &args, !! 95 args.handler = &task_in_intr;
>> 96 return ide_raw_taskfile(drive, &args, buf);
103 } 97 }
104 98
105 static int inline task_dma_ok(ide_task_t *task !! 99 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
106 { 100 {
107 if (blk_fs_request(task->rq) || (task- !! 101 ide_hwif_t *hwif = HWIF(drive);
108 return 1; !! 102 task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
>> 103 hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
>> 104 u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;
>> 105
>> 106 /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
>> 107 if (IDE_CONTROL_REG) {
>> 108 /* clear nIEN */
>> 109 hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
>> 110 }
>> 111 SELECT_MASK(drive, 0);
>> 112
>> 113 if (drive->addressing == 1) {
>> 114 hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
>> 115 hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
>> 116 hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
>> 117 hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
>> 118 hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
>> 119 }
>> 120
>> 121 hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
>> 122 hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
>> 123 hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
>> 124 hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
>> 125 hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
>> 126
>> 127 hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
>> 128
>> 129 if (task->handler != NULL) {
>> 130 if (task->prehandler != NULL) {
>> 131 hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
>> 132 ndelay(400); /* FIXME */
>> 133 return task->prehandler(drive, task->rq);
>> 134 }
>> 135 ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
>> 136 return ide_started;
>> 137 }
109 138
110 switch (task->tf.command) { !! 139 if (!drive->using_dma)
>> 140 return ide_stopped;
>> 141
>> 142 switch (taskfile->command) {
111 case WIN_WRITEDMA_ONCE: 143 case WIN_WRITEDMA_ONCE:
112 case WIN_WRITEDMA: 144 case WIN_WRITEDMA:
113 case WIN_WRITEDMA_EXT: 145 case WIN_WRITEDMA_EXT:
114 case WIN_READDMA_ONCE: 146 case WIN_READDMA_ONCE:
115 case WIN_READDMA: 147 case WIN_READDMA:
116 case WIN_READDMA_EXT: 148 case WIN_READDMA_EXT:
117 case WIN_IDENTIFY_DMA: 149 case WIN_IDENTIFY_DMA:
118 return 1; !! 150 if (!hwif->dma_setup(drive)) {
>> 151 hwif->dma_exec_cmd(drive, taskfile->command);
>> 152 hwif->dma_start(drive);
>> 153 return ide_started;
>> 154 }
>> 155 break;
>> 156 default:
>> 157 if (task->handler == NULL)
>> 158 return ide_stopped;
119 } 159 }
120 160
121 return 0; !! 161 return ide_stopped;
122 } 162 }
123 163
124 static ide_startstop_t task_no_data_intr(ide_d !! 164 EXPORT_SYMBOL(do_rw_taskfile);
125 static ide_startstop_t set_geometry_intr(ide_d <<
126 static ide_startstop_t recal_intr(ide_drive_t <<
127 static ide_startstop_t set_multmode_intr(ide_d <<
128 static ide_startstop_t pre_task_out_intr(ide_d <<
129 static ide_startstop_t task_in_intr(ide_drive_ <<
130 <<
131 ide_startstop_t do_rw_taskfile (ide_drive_t *d <<
132 { <<
133 ide_hwif_t *hwif = HWIF(drive); <<
134 struct ide_taskfile *tf = &task->tf; <<
135 ide_handler_t *handler = NULL; <<
136 <<
137 if (task->data_phase == TASKFILE_MULTI <<
138 task->data_phase == TASKFILE_MULTI <<
139 if (!drive->mult_count) { <<
140 printk(KERN_ERR "%s: m <<
141 drive- <<
142 return ide_stopped; <<
143 } <<
144 } <<
145 <<
146 if (task->tf_flags & IDE_TFLAG_FLAGGED <<
147 task->tf_flags |= IDE_TFLAG_FL <<
148 <<
149 if ((task->tf_flags & IDE_TFLAG_DMA_PI <<
150 ide_tf_load(drive, task); <<
151 <<
152 switch (task->data_phase) { <<
153 case TASKFILE_MULTI_OUT: <<
154 case TASKFILE_OUT: <<
155 hwif->OUTBSYNC(drive, tf->comm <<
156 ndelay(400); /* FIXME */ <<
157 return pre_task_out_intr(drive <<
158 case TASKFILE_MULTI_IN: <<
159 case TASKFILE_IN: <<
160 handler = task_in_intr; <<
161 /* fall-through */ <<
162 case TASKFILE_NO_DATA: <<
163 if (handler == NULL) <<
164 handler = task_no_data <<
165 /* WIN_{SPECIFY,RESTORE,SETMUL <<
166 if (task->tf_flags & IDE_TFLAG <<
167 switch (tf->command) { <<
168 case WIN_SPECIFY: hand <<
169 case WIN_RESTORE: hand <<
170 case WIN_SETMULT: hand <<
171 } <<
172 } <<
173 ide_execute_command(drive, tf- <<
174 WAIT_WORST <<
175 return ide_started; <<
176 default: <<
177 if (task_dma_ok(task) == 0 || <<
178 hwif->dma_setup(drive)) <<
179 return ide_stopped; <<
180 hwif->dma_exec_cmd(drive, tf-> <<
181 hwif->dma_start(drive); <<
182 return ide_started; <<
183 } <<
184 } <<
185 EXPORT_SYMBOL_GPL(do_rw_taskfile); <<
186 165
187 /* 166 /*
188 * set_multmode_intr() is invoked on completio 167 * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
189 */ 168 */
190 static ide_startstop_t set_multmode_intr(ide_d !! 169 ide_startstop_t set_multmode_intr (ide_drive_t *drive)
191 { 170 {
192 u8 stat = ide_read_status(drive); !! 171 ide_hwif_t *hwif = HWIF(drive);
>> 172 u8 stat;
193 173
194 if (OK_STAT(stat, READY_STAT, BAD_STAT !! 174 if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
195 drive->mult_count = drive->mul 175 drive->mult_count = drive->mult_req;
196 else { !! 176 } else {
197 drive->mult_req = drive->mult_ 177 drive->mult_req = drive->mult_count = 0;
198 drive->special.b.recalibrate = 178 drive->special.b.recalibrate = 1;
199 (void) ide_dump_status(drive, 179 (void) ide_dump_status(drive, "set_multmode", stat);
200 } 180 }
201 return ide_stopped; 181 return ide_stopped;
202 } 182 }
203 183
>> 184 EXPORT_SYMBOL(set_multmode_intr);
>> 185
204 /* 186 /*
205 * set_geometry_intr() is invoked on completio 187 * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
206 */ 188 */
207 static ide_startstop_t set_geometry_intr(ide_d !! 189 ide_startstop_t set_geometry_intr (ide_drive_t *drive)
208 { 190 {
>> 191 ide_hwif_t *hwif = HWIF(drive);
209 int retries = 5; 192 int retries = 5;
210 u8 stat; 193 u8 stat;
211 194
212 while (((stat = ide_read_status(drive) !! 195 while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
213 udelay(10); 196 udelay(10);
214 197
215 if (OK_STAT(stat, READY_STAT, BAD_STAT 198 if (OK_STAT(stat, READY_STAT, BAD_STAT))
216 return ide_stopped; 199 return ide_stopped;
217 200
218 if (stat & (ERR_STAT|DRQ_STAT)) 201 if (stat & (ERR_STAT|DRQ_STAT))
219 return ide_error(drive, "set_g 202 return ide_error(drive, "set_geometry_intr", stat);
220 203
221 BUG_ON(HWGROUP(drive)->handler != NULL !! 204 if (HWGROUP(drive)->handler != NULL)
>> 205 BUG();
222 ide_set_handler(drive, &set_geometry_i 206 ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
223 return ide_started; 207 return ide_started;
224 } 208 }
225 209
>> 210 EXPORT_SYMBOL(set_geometry_intr);
>> 211
226 /* 212 /*
227 * recal_intr() is invoked on completion of a 213 * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
228 */ 214 */
229 static ide_startstop_t recal_intr(ide_drive_t !! 215 ide_startstop_t recal_intr (ide_drive_t *drive)
230 { 216 {
231 u8 stat = ide_read_status(drive); !! 217 ide_hwif_t *hwif = HWIF(drive);
>> 218 u8 stat;
232 219
233 if (!OK_STAT(stat, READY_STAT, BAD_STA !! 220 if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT))
234 return ide_error(drive, "recal 221 return ide_error(drive, "recal_intr", stat);
235 return ide_stopped; 222 return ide_stopped;
236 } 223 }
237 224
>> 225 EXPORT_SYMBOL(recal_intr);
>> 226
238 /* 227 /*
239 * Handler for commands without a data phase 228 * Handler for commands without a data phase
240 */ 229 */
241 static ide_startstop_t task_no_data_intr(ide_d !! 230 ide_startstop_t task_no_data_intr (ide_drive_t *drive)
242 { 231 {
243 ide_task_t *args = HWGROUP(driv 232 ide_task_t *args = HWGROUP(drive)->rq->special;
>> 233 ide_hwif_t *hwif = HWIF(drive);
244 u8 stat; 234 u8 stat;
245 235
246 local_irq_enable_in_hardirq(); !! 236 local_irq_enable();
247 stat = ide_read_status(drive); !! 237 if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
248 <<
249 if (!OK_STAT(stat, READY_STAT, BAD_STA <<
250 return ide_error(drive, "task_ 238 return ide_error(drive, "task_no_data_intr", stat);
251 /* calls ide_end_drive_cmd */ 239 /* calls ide_end_drive_cmd */
252 !! 240 }
253 if (args) 241 if (args)
254 ide_end_drive_cmd(drive, stat, !! 242 ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
255 243
256 return ide_stopped; 244 return ide_stopped;
257 } 245 }
258 246
>> 247 EXPORT_SYMBOL(task_no_data_intr);
>> 248
259 static u8 wait_drive_not_busy(ide_drive_t *dri 249 static u8 wait_drive_not_busy(ide_drive_t *drive)
260 { 250 {
261 int retries; !! 251 ide_hwif_t *hwif = HWIF(drive);
>> 252 int retries = 100;
262 u8 stat; 253 u8 stat;
263 254
264 /* 255 /*
265 * Last sector was transfered, wait un 256 * Last sector was transfered, wait until drive is ready.
266 * This can take up to 10 usec, but we !! 257 * This can take up to 10 usec, but we will wait max 1 ms
>> 258 * (drive_cmd_intr() waits that long).
267 */ 259 */
268 for (retries = 0; retries < 100; retri !! 260 while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
269 stat = ide_read_status(drive); !! 261 udelay(10);
270 <<
271 if (stat & BUSY_STAT) <<
272 udelay(10); <<
273 else <<
274 break; <<
275 } <<
276 262
277 if (stat & BUSY_STAT) !! 263 if (!retries)
278 printk(KERN_ERR "%s: drive sti 264 printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
279 265
280 return stat; 266 return stat;
281 } 267 }
282 268
283 static void ide_pio_sector(ide_drive_t *drive, 269 static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
284 { 270 {
285 ide_hwif_t *hwif = drive->hwif; 271 ide_hwif_t *hwif = drive->hwif;
286 struct scatterlist *sg = hwif->sg_tabl 272 struct scatterlist *sg = hwif->sg_table;
287 struct scatterlist *cursg = hwif->curs <<
288 struct page *page; 273 struct page *page;
289 #ifdef CONFIG_HIGHMEM 274 #ifdef CONFIG_HIGHMEM
290 unsigned long flags; 275 unsigned long flags;
291 #endif 276 #endif
292 unsigned int offset; 277 unsigned int offset;
293 u8 *buf; 278 u8 *buf;
294 279
295 cursg = hwif->cursg; !! 280 page = sg[hwif->cursg].page;
296 if (!cursg) { !! 281 offset = sg[hwif->cursg].offset + hwif->cursg_ofs * SECTOR_SIZE;
297 cursg = sg; <<
298 hwif->cursg = sg; <<
299 } <<
300 <<
301 page = sg_page(cursg); <<
302 offset = cursg->offset + hwif->cursg_o <<
303 282
304 /* get the current page and offset */ 283 /* get the current page and offset */
305 page = nth_page(page, (offset >> PAGE_ 284 page = nth_page(page, (offset >> PAGE_SHIFT));
306 offset %= PAGE_SIZE; 285 offset %= PAGE_SIZE;
307 286
308 #ifdef CONFIG_HIGHMEM 287 #ifdef CONFIG_HIGHMEM
309 local_irq_save(flags); 288 local_irq_save(flags);
310 #endif 289 #endif
311 buf = kmap_atomic(page, KM_BIO_SRC_IRQ 290 buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
312 291
313 hwif->nleft--; 292 hwif->nleft--;
314 hwif->cursg_ofs++; 293 hwif->cursg_ofs++;
315 294
316 if ((hwif->cursg_ofs * SECTOR_SIZE) == !! 295 if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) {
317 hwif->cursg = sg_next(hwif->cu !! 296 hwif->cursg++;
318 hwif->cursg_ofs = 0; 297 hwif->cursg_ofs = 0;
319 } 298 }
320 299
321 /* do the actual data transfer */ 300 /* do the actual data transfer */
322 if (write) 301 if (write)
323 hwif->ata_output_data(drive, b !! 302 taskfile_output_data(drive, buf, SECTOR_WORDS);
324 else 303 else
325 hwif->ata_input_data(drive, bu !! 304 taskfile_input_data(drive, buf, SECTOR_WORDS);
326 305
327 kunmap_atomic(buf, KM_BIO_SRC_IRQ); 306 kunmap_atomic(buf, KM_BIO_SRC_IRQ);
328 #ifdef CONFIG_HIGHMEM 307 #ifdef CONFIG_HIGHMEM
329 local_irq_restore(flags); 308 local_irq_restore(flags);
330 #endif 309 #endif
331 } 310 }
332 311
333 static void ide_pio_multi(ide_drive_t *drive, 312 static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
334 { 313 {
335 unsigned int nsect; 314 unsigned int nsect;
336 315
337 nsect = min_t(unsigned int, drive->hwi 316 nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
338 while (nsect--) 317 while (nsect--)
339 ide_pio_sector(drive, write); 318 ide_pio_sector(drive, write);
340 } 319 }
341 320
342 static void ide_pio_datablock(ide_drive_t *dri !! 321 static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
343 unsigned 322 unsigned int write)
344 { 323 {
345 u8 saved_io_32bit = drive->io_32bit; <<
346 <<
347 if (rq->bio) /* fs request */ 324 if (rq->bio) /* fs request */
348 rq->errors = 0; 325 rq->errors = 0;
349 326
350 if (rq->cmd_type == REQ_TYPE_ATA_TASKF <<
351 ide_task_t *task = rq->special <<
352 <<
353 if (task->tf_flags & IDE_TFLAG <<
354 drive->io_32bit = 0; <<
355 } <<
356 <<
357 touch_softlockup_watchdog(); <<
358 <<
359 switch (drive->hwif->data_phase) { 327 switch (drive->hwif->data_phase) {
360 case TASKFILE_MULTI_IN: 328 case TASKFILE_MULTI_IN:
361 case TASKFILE_MULTI_OUT: 329 case TASKFILE_MULTI_OUT:
362 ide_pio_multi(drive, write); 330 ide_pio_multi(drive, write);
363 break; 331 break;
364 default: 332 default:
365 ide_pio_sector(drive, write); 333 ide_pio_sector(drive, write);
366 break; 334 break;
367 } 335 }
368 <<
369 drive->io_32bit = saved_io_32bit; <<
370 } 336 }
371 337
372 static ide_startstop_t task_error(ide_drive_t 338 static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
373 const char * 339 const char *s, u8 stat)
374 { 340 {
375 if (rq->bio) { 341 if (rq->bio) {
376 ide_hwif_t *hwif = drive->hwif 342 ide_hwif_t *hwif = drive->hwif;
377 int sectors = hwif->nsect - hw 343 int sectors = hwif->nsect - hwif->nleft;
378 344
379 switch (hwif->data_phase) { 345 switch (hwif->data_phase) {
380 case TASKFILE_IN: 346 case TASKFILE_IN:
381 if (hwif->nleft) 347 if (hwif->nleft)
382 break; 348 break;
383 /* fall through */ 349 /* fall through */
384 case TASKFILE_OUT: 350 case TASKFILE_OUT:
385 sectors--; 351 sectors--;
386 break; 352 break;
387 case TASKFILE_MULTI_IN: 353 case TASKFILE_MULTI_IN:
388 if (hwif->nleft) 354 if (hwif->nleft)
389 break; 355 break;
390 /* fall through */ 356 /* fall through */
391 case TASKFILE_MULTI_OUT: 357 case TASKFILE_MULTI_OUT:
392 sectors -= drive->mult 358 sectors -= drive->mult_count;
393 default: 359 default:
394 break; 360 break;
395 } 361 }
396 362
397 if (sectors > 0) { !! 363 if (sectors > 0)
398 ide_driver_t *drv; !! 364 drive->driver->end_request(drive, 1, sectors);
399 <<
400 drv = *(ide_driver_t * <<
401 drv->end_request(drive <<
402 } <<
403 } 365 }
404 return ide_error(drive, s, stat); 366 return ide_error(drive, s, stat);
405 } 367 }
406 368
407 void task_end_request(ide_drive_t *drive, stru !! 369 static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
408 { 370 {
409 if (rq->cmd_type == REQ_TYPE_ATA_TASKF !! 371 if (rq->flags & REQ_DRIVE_TASKFILE) {
410 u8 err = ide_read_error(drive) !! 372 ide_task_t *task = rq->special;
411 <<
412 ide_end_drive_cmd(drive, stat, <<
413 return; <<
414 } <<
415 <<
416 if (rq->rq_disk) { <<
417 ide_driver_t *drv; <<
418 <<
419 drv = *(ide_driver_t **)rq->rq <<
420 drv->end_request(drive, 1, rq- <<
421 } else <<
422 ide_end_request(drive, 1, rq-> <<
423 } <<
424 373
425 /* !! 374 if (task->tf_out_flags.all) {
426 * We got an interrupt on a task_in case, but !! 375 u8 err = drive->hwif->INB(IDE_ERROR_REG);
427 * !! 376 ide_end_drive_cmd(drive, stat, err);
428 * It might be a spurious irq (shared irq), bu !! 377 return;
429 * command that had no output. !! 378 }
430 */ <<
431 static ide_startstop_t task_in_unexpected(ide_ <<
432 { <<
433 /* Command all done? */ <<
434 if (OK_STAT(stat, READY_STAT, BUSY_STA <<
435 task_end_request(drive, rq, st <<
436 return ide_stopped; <<
437 } 379 }
438 !! 380 drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
439 /* Assume it was a spurious irq */ <<
440 ide_set_handler(drive, &task_in_intr, <<
441 return ide_started; <<
442 } 381 }
443 382
444 /* 383 /*
445 * Handler for command with PIO data-in phase 384 * Handler for command with PIO data-in phase (Read/Read Multiple).
446 */ 385 */
447 static ide_startstop_t task_in_intr(ide_drive_ !! 386 ide_startstop_t task_in_intr (ide_drive_t *drive)
448 { 387 {
449 ide_hwif_t *hwif = drive->hwif; 388 ide_hwif_t *hwif = drive->hwif;
450 struct request *rq = HWGROUP(drive)->r 389 struct request *rq = HWGROUP(drive)->rq;
451 u8 stat = ide_read_status(drive); !! 390 u8 stat = hwif->INB(IDE_STATUS_REG);
452 391
453 /* Error? */ !! 392 /* new way for dealing with premature shared PCI interrupts */
454 if (stat & ERR_STAT) !! 393 if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
455 return task_error(drive, rq, _ !! 394 if (stat & (ERR_STAT | DRQ_STAT))
456 !! 395 return task_error(drive, rq, __FUNCTION__, stat);
457 /* Didn't want any data? Odd. */ !! 396 /* No data yet, so wait for another IRQ. */
458 if (!(stat & DRQ_STAT)) !! 397 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
459 return task_in_unexpected(driv !! 398 return ide_started;
>> 399 }
460 400
461 ide_pio_datablock(drive, rq, 0); 401 ide_pio_datablock(drive, rq, 0);
462 402
463 /* Are we done? Check status and finis !! 403 /* If it was the last datablock check status and finish transfer. */
464 if (!hwif->nleft) { 404 if (!hwif->nleft) {
465 stat = wait_drive_not_busy(dri 405 stat = wait_drive_not_busy(drive);
466 if (!OK_STAT(stat, 0, BAD_STAT !! 406 if (!OK_STAT(stat, 0, BAD_R_STAT))
467 return task_error(driv 407 return task_error(drive, rq, __FUNCTION__, stat);
468 task_end_request(drive, rq, st 408 task_end_request(drive, rq, stat);
469 return ide_stopped; 409 return ide_stopped;
470 } 410 }
471 411
472 /* Still data left to transfer. */ 412 /* Still data left to transfer. */
473 ide_set_handler(drive, &task_in_intr, 413 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
474 414
475 return ide_started; 415 return ide_started;
476 } 416 }
>> 417 EXPORT_SYMBOL(task_in_intr);
477 418
478 /* 419 /*
479 * Handler for command with PIO data-out phase 420 * Handler for command with PIO data-out phase (Write/Write Multiple).
480 */ 421 */
481 static ide_startstop_t task_out_intr (ide_driv 422 static ide_startstop_t task_out_intr (ide_drive_t *drive)
482 { 423 {
483 ide_hwif_t *hwif = drive->hwif; 424 ide_hwif_t *hwif = drive->hwif;
484 struct request *rq = HWGROUP(drive)->r 425 struct request *rq = HWGROUP(drive)->rq;
485 u8 stat = ide_read_status(drive); !! 426 u8 stat = hwif->INB(IDE_STATUS_REG);
486 427
487 if (!OK_STAT(stat, DRIVE_READY, drive- 428 if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
488 return task_error(drive, rq, _ 429 return task_error(drive, rq, __FUNCTION__, stat);
489 430
490 /* Deal with unexpected ATA data phase 431 /* Deal with unexpected ATA data phase. */
491 if (((stat & DRQ_STAT) == 0) ^ !hwif-> 432 if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
492 return task_error(drive, rq, _ 433 return task_error(drive, rq, __FUNCTION__, stat);
493 434
494 if (!hwif->nleft) { 435 if (!hwif->nleft) {
495 task_end_request(drive, rq, st 436 task_end_request(drive, rq, stat);
496 return ide_stopped; 437 return ide_stopped;
497 } 438 }
498 439
499 /* Still data left to transfer. */ 440 /* Still data left to transfer. */
500 ide_pio_datablock(drive, rq, 1); 441 ide_pio_datablock(drive, rq, 1);
501 ide_set_handler(drive, &task_out_intr, 442 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
502 443
503 return ide_started; 444 return ide_started;
504 } 445 }
505 446
506 static ide_startstop_t pre_task_out_intr(ide_d !! 447 ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
507 { 448 {
508 ide_startstop_t startstop; 449 ide_startstop_t startstop;
509 450
510 if (ide_wait_stat(&startstop, drive, D !! 451 if (ide_wait_stat(&startstop, drive, DATA_READY,
511 drive->bad_wstat, WA 452 drive->bad_wstat, WAIT_DRQ)) {
512 printk(KERN_ERR "%s: no DRQ af 453 printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
513 drive->name, 454 drive->name,
514 drive->hwif->d 455 drive->hwif->data_phase ? "MULT" : "",
515 drive->address 456 drive->addressing ? "_EXT" : "");
516 return startstop; 457 return startstop;
517 } 458 }
518 459
519 if (!drive->unmask) 460 if (!drive->unmask)
520 local_irq_disable(); 461 local_irq_disable();
521 462
522 ide_set_handler(drive, &task_out_intr, 463 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
523 ide_pio_datablock(drive, rq, 1); 464 ide_pio_datablock(drive, rq, 1);
524 465
525 return ide_started; 466 return ide_started;
526 } 467 }
>> 468 EXPORT_SYMBOL(pre_task_out_intr);
527 469
528 int ide_raw_taskfile(ide_drive_t *drive, ide_t !! 470 static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
529 { 471 {
530 struct request rq; 472 struct request rq;
531 473
532 memset(&rq, 0, sizeof(rq)); 474 memset(&rq, 0, sizeof(rq));
533 rq.ref_count = 1; !! 475 rq.flags = REQ_DRIVE_TASKFILE;
534 rq.cmd_type = REQ_TYPE_ATA_TASKFILE; <<
535 rq.buffer = buf; 476 rq.buffer = buf;
536 477
537 /* 478 /*
538 * (ks) We transfer currently only who 479 * (ks) We transfer currently only whole sectors.
539 * This is suffient for now. But, it 480 * This is suffient for now. But, it would be great,
540 * if we would find a solution to tran 481 * if we would find a solution to transfer any size.
541 * To support special commands like RE 482 * To support special commands like READ LONG.
542 */ 483 */
543 rq.hard_nr_sectors = rq.nr_sectors = n !! 484 if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
544 rq.hard_cur_sectors = rq.current_nr_se !! 485 if (data_size == 0)
>> 486 rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
>> 487 else
>> 488 rq.nr_sectors = data_size / SECTOR_SIZE;
545 489
546 if (task->tf_flags & IDE_TFLAG_WRITE) !! 490 if (!rq.nr_sectors) {
547 rq.cmd_flags |= REQ_RW; !! 491 printk(KERN_ERR "%s: in/out command without data\n",
>> 492 drive->name);
>> 493 return -EFAULT;
>> 494 }
548 495
549 rq.special = task; !! 496 rq.hard_nr_sectors = rq.nr_sectors;
550 task->rq = &rq; !! 497 rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
>> 498
>> 499 if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
>> 500 rq.flags |= REQ_RW;
>> 501 }
551 502
>> 503 rq.special = args;
552 return ide_do_drive_cmd(drive, &rq, id 504 return ide_do_drive_cmd(drive, &rq, ide_wait);
553 } 505 }
554 506
555 EXPORT_SYMBOL(ide_raw_taskfile); !! 507 int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
556 <<
557 int ide_no_data_taskfile(ide_drive_t *drive, i <<
558 { 508 {
559 task->data_phase = TASKFILE_NO_DATA; !! 509 return ide_diag_taskfile(drive, args, 0, buf);
560 <<
561 return ide_raw_taskfile(drive, task, N <<
562 } 510 }
563 EXPORT_SYMBOL_GPL(ide_no_data_taskfile); <<
564 511
565 #ifdef CONFIG_IDE_TASK_IOCTL !! 512 EXPORT_SYMBOL(ide_raw_taskfile);
>> 513
566 int ide_taskfile_ioctl (ide_drive_t *drive, un 514 int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
567 { 515 {
568 ide_task_request_t *req_task; 516 ide_task_request_t *req_task;
569 ide_task_t args; 517 ide_task_t args;
570 u8 *outbuf = NULL; 518 u8 *outbuf = NULL;
571 u8 *inbuf = NULL; 519 u8 *inbuf = NULL;
572 u8 *data_buf = NULL; !! 520 task_ioreg_t *argsptr = args.tfRegister;
>> 521 task_ioreg_t *hobsptr = args.hobRegister;
573 int err = 0; 522 int err = 0;
574 int tasksize = sizeof(struc 523 int tasksize = sizeof(struct ide_task_request_s);
575 unsigned int taskin = 0; !! 524 int taskin = 0;
576 unsigned int taskout = 0; !! 525 int taskout = 0;
577 u16 nsect = 0; !! 526 u8 io_32bit = drive->io_32bit;
578 char __user *buf = (char __user *)arg; 527 char __user *buf = (char __user *)arg;
579 528
580 // printk("IDE Taskfile ...\n"); 529 // printk("IDE Taskfile ...\n");
581 530
582 req_task = kzalloc(tasksize, GFP_KERNE !! 531 req_task = kmalloc(tasksize, GFP_KERNEL);
583 if (req_task == NULL) return -ENOMEM; 532 if (req_task == NULL) return -ENOMEM;
>> 533 memset(req_task, 0, tasksize);
584 if (copy_from_user(req_task, buf, task 534 if (copy_from_user(req_task, buf, tasksize)) {
585 kfree(req_task); 535 kfree(req_task);
586 return -EFAULT; 536 return -EFAULT;
587 } 537 }
588 538
589 taskout = req_task->out_size; !! 539 taskout = (int) req_task->out_size;
590 taskin = req_task->in_size; !! 540 taskin = (int) req_task->in_size;
591 <<
592 if (taskin > 65536 || taskout > 65536) <<
593 err = -EINVAL; <<
594 goto abort; <<
595 } <<
596 541
597 if (taskout) { 542 if (taskout) {
598 int outtotal = tasksize; 543 int outtotal = tasksize;
599 outbuf = kzalloc(taskout, GFP_ !! 544 outbuf = kmalloc(taskout, GFP_KERNEL);
600 if (outbuf == NULL) { 545 if (outbuf == NULL) {
601 err = -ENOMEM; 546 err = -ENOMEM;
602 goto abort; 547 goto abort;
603 } 548 }
>> 549 memset(outbuf, 0, taskout);
604 if (copy_from_user(outbuf, buf 550 if (copy_from_user(outbuf, buf + outtotal, taskout)) {
605 err = -EFAULT; 551 err = -EFAULT;
606 goto abort; 552 goto abort;
607 } 553 }
608 } 554 }
609 555
610 if (taskin) { 556 if (taskin) {
611 int intotal = tasksize + tasko 557 int intotal = tasksize + taskout;
612 inbuf = kzalloc(taskin, GFP_KE !! 558 inbuf = kmalloc(taskin, GFP_KERNEL);
613 if (inbuf == NULL) { 559 if (inbuf == NULL) {
614 err = -ENOMEM; 560 err = -ENOMEM;
615 goto abort; 561 goto abort;
616 } 562 }
>> 563 memset(inbuf, 0, taskin);
617 if (copy_from_user(inbuf, buf 564 if (copy_from_user(inbuf, buf + intotal, taskin)) {
618 err = -EFAULT; 565 err = -EFAULT;
619 goto abort; 566 goto abort;
620 } 567 }
621 } 568 }
622 569
623 memset(&args, 0, sizeof(ide_task_t)); 570 memset(&args, 0, sizeof(ide_task_t));
>> 571 memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
>> 572 memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
624 573
625 memcpy(&args.tf_array[0], req_task->ho !! 574 args.tf_in_flags = req_task->in_flags;
626 memcpy(&args.tf_array[6], req_task->io !! 575 args.tf_out_flags = req_task->out_flags;
627 !! 576 args.data_phase = req_task->data_phase;
628 args.data_phase = req_task->data_phase !! 577 args.command_type = req_task->req_cmd;
629 <<
630 args.tf_flags = IDE_TFLAG_IO_16BIT | I <<
631 IDE_TFLAG_IN_TF; <<
632 if (drive->addressing == 1) <<
633 args.tf_flags |= (IDE_TFLAG_LB <<
634 <<
635 if (req_task->out_flags.all) { <<
636 args.tf_flags |= IDE_TFLAG_FLA <<
637 <<
638 if (req_task->out_flags.b.data <<
639 args.tf_flags |= IDE_T <<
640 <<
641 if (req_task->out_flags.b.nsec <<
642 args.tf_flags |= IDE_T <<
643 if (req_task->out_flags.b.sect <<
644 args.tf_flags |= IDE_T <<
645 if (req_task->out_flags.b.lcyl <<
646 args.tf_flags |= IDE_T <<
647 if (req_task->out_flags.b.hcyl <<
648 args.tf_flags |= IDE_T <<
649 <<
650 if (req_task->out_flags.b.erro <<
651 args.tf_flags |= IDE_T <<
652 if (req_task->out_flags.b.nsec <<
653 args.tf_flags |= IDE_T <<
654 if (req_task->out_flags.b.sect <<
655 args.tf_flags |= IDE_T <<
656 if (req_task->out_flags.b.lcyl <<
657 args.tf_flags |= IDE_T <<
658 if (req_task->out_flags.b.hcyl <<
659 args.tf_flags |= IDE_T <<
660 } else { <<
661 args.tf_flags |= IDE_TFLAG_OUT <<
662 if (args.tf_flags & IDE_TFLAG_ <<
663 args.tf_flags |= IDE_T <<
664 } <<
665 <<
666 if (req_task->in_flags.b.data) <<
667 args.tf_flags |= IDE_TFLAG_IN_ <<
668 578
>> 579 drive->io_32bit = 0;
669 switch(req_task->data_phase) { 580 switch(req_task->data_phase) {
>> 581 case TASKFILE_OUT_DMAQ:
>> 582 case TASKFILE_OUT_DMA:
>> 583 err = ide_diag_taskfile(drive, &args, taskout, outbuf);
>> 584 break;
>> 585 case TASKFILE_IN_DMAQ:
>> 586 case TASKFILE_IN_DMA:
>> 587 err = ide_diag_taskfile(drive, &args, taskin, inbuf);
>> 588 break;
670 case TASKFILE_MULTI_OUT: 589 case TASKFILE_MULTI_OUT:
671 if (!drive->mult_count 590 if (!drive->mult_count) {
672 /* (hs): give 591 /* (hs): give up if multcount is not set */
673 printk(KERN_ER 592 printk(KERN_ERR "%s: %s Multimode Write " \
674 "multc 593 "multcount is not set\n",
675 drive- 594 drive->name, __FUNCTION__);
676 err = -EPERM; 595 err = -EPERM;
677 goto abort; 596 goto abort;
678 } 597 }
679 /* fall through */ 598 /* fall through */
680 case TASKFILE_OUT: 599 case TASKFILE_OUT:
681 /* fall through */ !! 600 args.prehandler = &pre_task_out_intr;
682 case TASKFILE_OUT_DMAQ: !! 601 args.handler = &task_out_intr;
683 case TASKFILE_OUT_DMA: !! 602 err = ide_diag_taskfile(drive, &args, taskout, outbuf);
684 nsect = taskout / SECT <<
685 data_buf = outbuf; <<
686 break; 603 break;
687 case TASKFILE_MULTI_IN: 604 case TASKFILE_MULTI_IN:
688 if (!drive->mult_count 605 if (!drive->mult_count) {
689 /* (hs): give 606 /* (hs): give up if multcount is not set */
690 printk(KERN_ER 607 printk(KERN_ERR "%s: %s Multimode Read failure " \
691 "multc 608 "multcount is not set\n",
692 drive- 609 drive->name, __FUNCTION__);
693 err = -EPERM; 610 err = -EPERM;
694 goto abort; 611 goto abort;
695 } 612 }
696 /* fall through */ 613 /* fall through */
697 case TASKFILE_IN: 614 case TASKFILE_IN:
698 /* fall through */ !! 615 args.handler = &task_in_intr;
699 case TASKFILE_IN_DMAQ: !! 616 err = ide_diag_taskfile(drive, &args, taskin, inbuf);
700 case TASKFILE_IN_DMA: <<
701 nsect = taskin / SECTO <<
702 data_buf = inbuf; <<
703 break; 617 break;
704 case TASKFILE_NO_DATA: 618 case TASKFILE_NO_DATA:
>> 619 args.handler = &task_no_data_intr;
>> 620 err = ide_diag_taskfile(drive, &args, 0, NULL);
705 break; 621 break;
706 default: 622 default:
707 err = -EFAULT; 623 err = -EFAULT;
708 goto abort; 624 goto abort;
709 } 625 }
710 626
711 if (req_task->req_cmd == IDE_DRIVE_TAS !! 627 memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
712 nsect = 0; !! 628 memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
713 else if (!nsect) { !! 629 req_task->in_flags = args.tf_in_flags;
714 nsect = (args.tf.hob_nsect << !! 630 req_task->out_flags = args.tf_out_flags;
715 <<
716 if (!nsect) { <<
717 printk(KERN_ERR "%s: i <<
718 drive- <<
719 err = -EFAULT; <<
720 goto abort; <<
721 } <<
722 } <<
723 <<
724 if (req_task->req_cmd == IDE_DRIVE_TAS <<
725 args.tf_flags |= IDE_TFLAG_WRI <<
726 <<
727 err = ide_raw_taskfile(drive, &args, d <<
728 <<
729 memcpy(req_task->hob_ports, &args.tf_a <<
730 memcpy(req_task->io_ports, &args.tf_ar <<
731 <<
732 if ((args.tf_flags & IDE_TFLAG_FLAGGED <<
733 req_task->in_flags.all == 0) { <<
734 req_task->in_flags.all = IDE_T <<
735 if (drive->addressing == 1) <<
736 req_task->in_flags.all <<
737 } <<
738 631
739 if (copy_to_user(buf, req_task, tasksi 632 if (copy_to_user(buf, req_task, tasksize)) {
740 err = -EFAULT; 633 err = -EFAULT;
741 goto abort; 634 goto abort;
742 } 635 }
743 if (taskout) { 636 if (taskout) {
744 int outtotal = tasksize; 637 int outtotal = tasksize;
745 if (copy_to_user(buf + outtota 638 if (copy_to_user(buf + outtotal, outbuf, taskout)) {
746 err = -EFAULT; 639 err = -EFAULT;
747 goto abort; 640 goto abort;
748 } 641 }
749 } 642 }
750 if (taskin) { 643 if (taskin) {
751 int intotal = tasksize + tasko 644 int intotal = tasksize + taskout;
752 if (copy_to_user(buf + intotal 645 if (copy_to_user(buf + intotal, inbuf, taskin)) {
753 err = -EFAULT; 646 err = -EFAULT;
754 goto abort; 647 goto abort;
755 } 648 }
756 } 649 }
757 abort: 650 abort:
758 kfree(req_task); 651 kfree(req_task);
759 kfree(outbuf); !! 652 if (outbuf != NULL)
760 kfree(inbuf); !! 653 kfree(outbuf);
>> 654 if (inbuf != NULL)
>> 655 kfree(inbuf);
761 656
762 // printk("IDE Taskfile ioctl ended. rc = 657 // printk("IDE Taskfile ioctl ended. rc = %i\n", err);
763 658
>> 659 drive->io_32bit = io_32bit;
>> 660
764 return err; 661 return err;
765 } 662 }
766 #endif <<
767 663
>> 664 int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
>> 665 {
>> 666 struct request rq;
>> 667 u8 buffer[4];
>> 668
>> 669 if (!buf)
>> 670 buf = buffer;
>> 671 memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
>> 672 ide_init_drive_cmd(&rq);
>> 673 rq.buffer = buf;
>> 674 *buf++ = cmd;
>> 675 *buf++ = nsect;
>> 676 *buf++ = feature;
>> 677 *buf++ = sectors;
>> 678 return ide_do_drive_cmd(drive, &rq, ide_wait);
>> 679 }
>> 680
>> 681 /*
>> 682 * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
>> 683 */
768 int ide_cmd_ioctl (ide_drive_t *drive, unsigne 684 int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
769 { 685 {
770 u8 *buf = NULL; !! 686 int err = 0;
771 int bufsize = 0, err = 0; !! 687 u8 args[4], *argbuf = args;
772 u8 args[4], xfer_rate = 0; !! 688 u8 xfer_rate = 0;
>> 689 int argsize = 4;
773 ide_task_t tfargs; 690 ide_task_t tfargs;
774 struct ide_taskfile *tf = &tfargs.tf; <<
775 struct hd_driveid *id = drive->id; <<
776 691
777 if (NULL == (void *) arg) { 692 if (NULL == (void *) arg) {
778 struct request rq; 693 struct request rq;
779 <<
780 ide_init_drive_cmd(&rq); 694 ide_init_drive_cmd(&rq);
781 rq.cmd_type = REQ_TYPE_ATA_TAS <<
782 <<
783 return ide_do_drive_cmd(drive, 695 return ide_do_drive_cmd(drive, &rq, ide_wait);
784 } 696 }
785 697
786 if (copy_from_user(args, (void __user 698 if (copy_from_user(args, (void __user *)arg, 4))
787 return -EFAULT; 699 return -EFAULT;
788 700
789 memset(&tfargs, 0, sizeof(ide_task_t)) 701 memset(&tfargs, 0, sizeof(ide_task_t));
790 tf->feature = args[2]; !! 702 tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
791 if (args[0] == WIN_SMART) { !! 703 tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
792 tf->nsect = args[3]; !! 704 tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1];
793 tf->lbal = args[1]; !! 705 tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00;
794 tf->lbam = 0x4f; !! 706 tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00;
795 tf->lbah = 0xc2; !! 707 tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00;
796 tfargs.tf_flags = IDE_TFLAG_OU !! 708 tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
797 } else { <<
798 tf->nsect = args[1]; <<
799 tfargs.tf_flags = IDE_TFLAG_OU <<
800 IDE_TFLAG_OU <<
801 } <<
802 tf->command = args[0]; <<
803 tfargs.data_phase = args[3] ? TASKFILE <<
804 709
805 if (args[3]) { 710 if (args[3]) {
806 tfargs.tf_flags |= IDE_TFLAG_I !! 711 argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
807 bufsize = SECTOR_WORDS * 4 * a !! 712 argbuf = kmalloc(argsize, GFP_KERNEL);
808 buf = kzalloc(bufsize, GFP_KER !! 713 if (argbuf == NULL)
809 if (buf == NULL) <<
810 return -ENOMEM; 714 return -ENOMEM;
>> 715 memcpy(argbuf, args, 4);
811 } 716 }
812 !! 717 if (set_transfer(drive, &tfargs)) {
813 if (tf->command == WIN_SETFEATURES && <<
814 tf->feature == SETFEATURES_XFER && <<
815 tf->nsect >= XFER_SW_DMA_0 && <<
816 (id->dma_ultra || id->dma_mword || <<
817 xfer_rate = args[1]; 718 xfer_rate = args[1];
818 if (tf->nsect > XFER_UDMA_2 && !! 719 if (ide_ata66_check(drive, &tfargs))
819 printk(KERN_WARNING "% <<
820 "b <<
821 goto abort; 720 goto abort;
822 } <<
823 } 721 }
824 722
825 err = ide_raw_taskfile(drive, &tfargs, !! 723 err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
826 <<
827 args[0] = tf->status; <<
828 args[1] = tf->error; <<
829 args[2] = tf->nsect; <<
830 724
831 if (!err && xfer_rate) { 725 if (!err && xfer_rate) {
832 /* active-retuning-calls futur 726 /* active-retuning-calls future */
833 ide_set_xfer_rate(drive, xfer_ 727 ide_set_xfer_rate(drive, xfer_rate);
834 ide_driveid_update(drive); 728 ide_driveid_update(drive);
835 } 729 }
836 abort: 730 abort:
837 if (copy_to_user((void __user *)arg, & !! 731 if (copy_to_user((void __user *)arg, argbuf, argsize))
838 err = -EFAULT; 732 err = -EFAULT;
839 if (buf) { !! 733 if (argsize > 4)
840 if (copy_to_user((void __user !! 734 kfree(argbuf);
841 err = -EFAULT; <<
842 kfree(buf); <<
843 } <<
844 return err; 735 return err;
845 } 736 }
846 737
>> 738 static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
>> 739 {
>> 740 struct request rq;
>> 741
>> 742 ide_init_drive_cmd(&rq);
>> 743 rq.flags = REQ_DRIVE_TASK;
>> 744 rq.buffer = buf;
>> 745 return ide_do_drive_cmd(drive, &rq, ide_wait);
>> 746 }
>> 747
>> 748 /*
>> 749 * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
>> 750 */
847 int ide_task_ioctl (ide_drive_t *drive, unsign 751 int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
848 { 752 {
849 void __user *p = (void __user *)arg; 753 void __user *p = (void __user *)arg;
850 int err = 0; 754 int err = 0;
851 u8 args[7]; !! 755 u8 args[7], *argbuf = args;
852 ide_task_t task; !! 756 int argsize = 7;
853 757
854 if (copy_from_user(args, p, 7)) 758 if (copy_from_user(args, p, 7))
855 return -EFAULT; 759 return -EFAULT;
>> 760 err = ide_wait_cmd_task(drive, argbuf);
>> 761 if (copy_to_user(p, argbuf, argsize))
>> 762 err = -EFAULT;
>> 763 return err;
>> 764 }
>> 765
>> 766 /*
>> 767 * NOTICE: This is additions from IBM to provide a discrete interface,
>> 768 * for selective taskregister access operations. Nice JOB Klaus!!!
>> 769 * Glad to be able to work and co-develop this with you and IBM.
>> 770 */
>> 771 ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
>> 772 {
>> 773 ide_hwif_t *hwif = HWIF(drive);
>> 774 task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
>> 775 hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
>> 776 #if DEBUG_TASKFILE
>> 777 u8 status;
>> 778 #endif
856 779
857 memset(&task, 0, sizeof(task)); !! 780 if (task->data_phase == TASKFILE_MULTI_IN ||
858 memcpy(&task.tf_array[7], &args[1], 6) !! 781 task->data_phase == TASKFILE_MULTI_OUT) {
859 task.tf.command = args[0]; !! 782 if (!drive->mult_count) {
860 task.tf_flags = IDE_TFLAG_TF | IDE_TFL !! 783 printk(KERN_ERR "%s: multimode not set!\n", drive->name);
>> 784 return ide_stopped;
>> 785 }
>> 786 }
861 787
862 err = ide_no_data_taskfile(drive, &tas !! 788 /*
>> 789 * (ks) Check taskfile in/out flags.
>> 790 * If set, then execute as it is defined.
>> 791 * If not set, then define default settings.
>> 792 * The default values are:
>> 793 * write and read all taskfile registers (except data)
>> 794 * write and read the hob registers (sector,nsector,lcyl,hcyl)
>> 795 */
>> 796 if (task->tf_out_flags.all == 0) {
>> 797 task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
>> 798 if (drive->addressing == 1)
>> 799 task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8);
>> 800 }
863 801
864 args[0] = task.tf.command; !! 802 if (task->tf_in_flags.all == 0) {
865 memcpy(&args[1], &task.tf_array[7], 6) !! 803 task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
>> 804 if (drive->addressing == 1)
>> 805 task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
>> 806 }
866 807
867 if (copy_to_user(p, args, 7)) !! 808 /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
868 err = -EFAULT; !! 809 if (IDE_CONTROL_REG)
>> 810 /* clear nIEN */
>> 811 hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
>> 812 SELECT_MASK(drive, 0);
>> 813
>> 814 #if DEBUG_TASKFILE
>> 815 status = hwif->INB(IDE_STATUS_REG);
>> 816 if (status & 0x80) {
>> 817 printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status);
>> 818 udelay(100);
>> 819 status = hwif->INB(IDE_STATUS_REG);
>> 820 printk("flagged_taskfile -> Status = %02x\n", status);
>> 821 }
>> 822 #endif
869 823
870 return err; !! 824 if (task->tf_out_flags.b.data) {
>> 825 u16 data = taskfile->data + (hobfile->data << 8);
>> 826 hwif->OUTW(data, IDE_DATA_REG);
>> 827 }
>> 828
>> 829 /* (ks) send hob registers first */
>> 830 if (task->tf_out_flags.b.nsector_hob)
>> 831 hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
>> 832 if (task->tf_out_flags.b.sector_hob)
>> 833 hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
>> 834 if (task->tf_out_flags.b.lcyl_hob)
>> 835 hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
>> 836 if (task->tf_out_flags.b.hcyl_hob)
>> 837 hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
>> 838
>> 839 /* (ks) Send now the standard registers */
>> 840 if (task->tf_out_flags.b.error_feature)
>> 841 hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
>> 842 /* refers to number of sectors to transfer */
>> 843 if (task->tf_out_flags.b.nsector)
>> 844 hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
>> 845 /* refers to sector offset or start sector */
>> 846 if (task->tf_out_flags.b.sector)
>> 847 hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
>> 848 if (task->tf_out_flags.b.lcyl)
>> 849 hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
>> 850 if (task->tf_out_flags.b.hcyl)
>> 851 hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
>> 852
>> 853 /*
>> 854 * (ks) In the flagged taskfile approch, we will use all specified
>> 855 * registers and the register value will not be changed, except the
>> 856 * select bit (master/slave) in the drive_head register. We must make
>> 857 * sure that the desired drive is selected.
>> 858 */
>> 859 hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
>> 860 switch(task->data_phase) {
>> 861
>> 862 case TASKFILE_OUT_DMAQ:
>> 863 case TASKFILE_OUT_DMA:
>> 864 case TASKFILE_IN_DMAQ:
>> 865 case TASKFILE_IN_DMA:
>> 866 hwif->dma_setup(drive);
>> 867 hwif->dma_exec_cmd(drive, taskfile->command);
>> 868 hwif->dma_start(drive);
>> 869 break;
>> 870
>> 871 default:
>> 872 if (task->handler == NULL)
>> 873 return ide_stopped;
>> 874
>> 875 /* Issue the command */
>> 876 if (task->prehandler) {
>> 877 hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
>> 878 ndelay(400); /* FIXME */
>> 879 return task->prehandler(drive, task->rq);
>> 880 }
>> 881 ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
>> 882 }
>> 883
>> 884 return ide_started;
871 } 885 }
872 886
| This page was automatically generated by the LXR engine. |