diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/ide/ide-lib.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/ide/ide-lib.c')
-rw-r--r-- | drivers/ide/ide-lib.c | 622 |
1 files changed, 622 insertions, 0 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c new file mode 100644 index 000000000000..6806d407e9c1 --- /dev/null +++ b/drivers/ide/ide-lib.c | |||
@@ -0,0 +1,622 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/types.h> | ||
4 | #include <linux/string.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/timer.h> | ||
7 | #include <linux/mm.h> | ||
8 | #include <linux/interrupt.h> | ||
9 | #include <linux/major.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/genhd.h> | ||
12 | #include <linux/blkpg.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/hdreg.h> | ||
17 | #include <linux/ide.h> | ||
18 | #include <linux/bitops.h> | ||
19 | |||
20 | #include <asm/byteorder.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/uaccess.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | /* | ||
26 | * IDE library routines. These are plug in code that most | ||
27 | * drivers can use but occasionally may be weird enough | ||
28 | * to want to do their own thing with | ||
29 | * | ||
30 | * Add common non I/O op stuff here. Make sure it has proper | ||
31 | * kernel-doc function headers or your patch will be rejected | ||
32 | */ | ||
33 | |||
34 | |||
35 | /** | ||
36 | * ide_xfer_verbose - return IDE mode names | ||
37 | * @xfer_rate: rate to name | ||
38 | * | ||
39 | * Returns a constant string giving the name of the mode | ||
40 | * requested. | ||
41 | */ | ||
42 | |||
43 | char *ide_xfer_verbose (u8 xfer_rate) | ||
44 | { | ||
45 | switch(xfer_rate) { | ||
46 | case XFER_UDMA_7: return("UDMA 7"); | ||
47 | case XFER_UDMA_6: return("UDMA 6"); | ||
48 | case XFER_UDMA_5: return("UDMA 5"); | ||
49 | case XFER_UDMA_4: return("UDMA 4"); | ||
50 | case XFER_UDMA_3: return("UDMA 3"); | ||
51 | case XFER_UDMA_2: return("UDMA 2"); | ||
52 | case XFER_UDMA_1: return("UDMA 1"); | ||
53 | case XFER_UDMA_0: return("UDMA 0"); | ||
54 | case XFER_MW_DMA_2: return("MW DMA 2"); | ||
55 | case XFER_MW_DMA_1: return("MW DMA 1"); | ||
56 | case XFER_MW_DMA_0: return("MW DMA 0"); | ||
57 | case XFER_SW_DMA_2: return("SW DMA 2"); | ||
58 | case XFER_SW_DMA_1: return("SW DMA 1"); | ||
59 | case XFER_SW_DMA_0: return("SW DMA 0"); | ||
60 | case XFER_PIO_4: return("PIO 4"); | ||
61 | case XFER_PIO_3: return("PIO 3"); | ||
62 | case XFER_PIO_2: return("PIO 2"); | ||
63 | case XFER_PIO_1: return("PIO 1"); | ||
64 | case XFER_PIO_0: return("PIO 0"); | ||
65 | case XFER_PIO_SLOW: return("PIO SLOW"); | ||
66 | default: return("XFER ERROR"); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | EXPORT_SYMBOL(ide_xfer_verbose); | ||
71 | |||
72 | /** | ||
73 | * ide_dma_speed - compute DMA speed | ||
74 | * @drive: drive | ||
75 | * @mode; intended mode | ||
76 | * | ||
77 | * Checks the drive capabilities and returns the speed to use | ||
78 | * for the transfer. Returns -1 if the requested mode is unknown | ||
79 | * (eg PIO) | ||
80 | */ | ||
81 | |||
82 | u8 ide_dma_speed(ide_drive_t *drive, u8 mode) | ||
83 | { | ||
84 | struct hd_driveid *id = drive->id; | ||
85 | ide_hwif_t *hwif = HWIF(drive); | ||
86 | u8 speed = 0; | ||
87 | |||
88 | if (drive->media != ide_disk && hwif->atapi_dma == 0) | ||
89 | return 0; | ||
90 | |||
91 | switch(mode) { | ||
92 | case 0x04: | ||
93 | if ((id->dma_ultra & 0x0040) && | ||
94 | (id->dma_ultra & hwif->ultra_mask)) | ||
95 | { speed = XFER_UDMA_6; break; } | ||
96 | case 0x03: | ||
97 | if ((id->dma_ultra & 0x0020) && | ||
98 | (id->dma_ultra & hwif->ultra_mask)) | ||
99 | { speed = XFER_UDMA_5; break; } | ||
100 | case 0x02: | ||
101 | if ((id->dma_ultra & 0x0010) && | ||
102 | (id->dma_ultra & hwif->ultra_mask)) | ||
103 | { speed = XFER_UDMA_4; break; } | ||
104 | if ((id->dma_ultra & 0x0008) && | ||
105 | (id->dma_ultra & hwif->ultra_mask)) | ||
106 | { speed = XFER_UDMA_3; break; } | ||
107 | case 0x01: | ||
108 | if ((id->dma_ultra & 0x0004) && | ||
109 | (id->dma_ultra & hwif->ultra_mask)) | ||
110 | { speed = XFER_UDMA_2; break; } | ||
111 | if ((id->dma_ultra & 0x0002) && | ||
112 | (id->dma_ultra & hwif->ultra_mask)) | ||
113 | { speed = XFER_UDMA_1; break; } | ||
114 | if ((id->dma_ultra & 0x0001) && | ||
115 | (id->dma_ultra & hwif->ultra_mask)) | ||
116 | { speed = XFER_UDMA_0; break; } | ||
117 | case 0x00: | ||
118 | if ((id->dma_mword & 0x0004) && | ||
119 | (id->dma_mword & hwif->mwdma_mask)) | ||
120 | { speed = XFER_MW_DMA_2; break; } | ||
121 | if ((id->dma_mword & 0x0002) && | ||
122 | (id->dma_mword & hwif->mwdma_mask)) | ||
123 | { speed = XFER_MW_DMA_1; break; } | ||
124 | if ((id->dma_mword & 0x0001) && | ||
125 | (id->dma_mword & hwif->mwdma_mask)) | ||
126 | { speed = XFER_MW_DMA_0; break; } | ||
127 | if ((id->dma_1word & 0x0004) && | ||
128 | (id->dma_1word & hwif->swdma_mask)) | ||
129 | { speed = XFER_SW_DMA_2; break; } | ||
130 | if ((id->dma_1word & 0x0002) && | ||
131 | (id->dma_1word & hwif->swdma_mask)) | ||
132 | { speed = XFER_SW_DMA_1; break; } | ||
133 | if ((id->dma_1word & 0x0001) && | ||
134 | (id->dma_1word & hwif->swdma_mask)) | ||
135 | { speed = XFER_SW_DMA_0; break; } | ||
136 | } | ||
137 | |||
138 | // printk("%s: %s: mode 0x%02x, speed 0x%02x\n", | ||
139 | // __FUNCTION__, drive->name, mode, speed); | ||
140 | |||
141 | return speed; | ||
142 | } | ||
143 | |||
144 | EXPORT_SYMBOL(ide_dma_speed); | ||
145 | |||
146 | |||
147 | /** | ||
148 | * ide_rate_filter - return best speed for mode | ||
149 | * @mode: modes available | ||
150 | * @speed: desired speed | ||
151 | * | ||
152 | * Given the available DMA/UDMA mode this function returns | ||
153 | * the best available speed at or below the speed requested. | ||
154 | */ | ||
155 | |||
156 | u8 ide_rate_filter (u8 mode, u8 speed) | ||
157 | { | ||
158 | #ifdef CONFIG_BLK_DEV_IDEDMA | ||
159 | static u8 speed_max[] = { | ||
160 | XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, | ||
161 | XFER_UDMA_5, XFER_UDMA_6 | ||
162 | }; | ||
163 | |||
164 | // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); | ||
165 | |||
166 | /* So that we remember to update this if new modes appear */ | ||
167 | if (mode > 4) | ||
168 | BUG(); | ||
169 | return min(speed, speed_max[mode]); | ||
170 | #else /* !CONFIG_BLK_DEV_IDEDMA */ | ||
171 | return min(speed, (u8)XFER_PIO_4); | ||
172 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | ||
173 | } | ||
174 | |||
175 | EXPORT_SYMBOL(ide_rate_filter); | ||
176 | |||
177 | int ide_dma_enable (ide_drive_t *drive) | ||
178 | { | ||
179 | ide_hwif_t *hwif = HWIF(drive); | ||
180 | struct hd_driveid *id = drive->id; | ||
181 | |||
182 | return ((int) ((((id->dma_ultra >> 8) & hwif->ultra_mask) || | ||
183 | ((id->dma_mword >> 8) & hwif->mwdma_mask) || | ||
184 | ((id->dma_1word >> 8) & hwif->swdma_mask)) ? 1 : 0)); | ||
185 | } | ||
186 | |||
187 | EXPORT_SYMBOL(ide_dma_enable); | ||
188 | |||
189 | /* | ||
190 | * Standard (generic) timings for PIO modes, from ATA2 specification. | ||
191 | * These timings are for access to the IDE data port register *only*. | ||
192 | * Some drives may specify a mode, while also specifying a different | ||
193 | * value for cycle_time (from drive identification data). | ||
194 | */ | ||
195 | const ide_pio_timings_t ide_pio_timings[6] = { | ||
196 | { 70, 165, 600 }, /* PIO Mode 0 */ | ||
197 | { 50, 125, 383 }, /* PIO Mode 1 */ | ||
198 | { 30, 100, 240 }, /* PIO Mode 2 */ | ||
199 | { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ | ||
200 | { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ | ||
201 | { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ | ||
202 | }; | ||
203 | |||
204 | EXPORT_SYMBOL_GPL(ide_pio_timings); | ||
205 | |||
206 | /* | ||
207 | * Shared data/functions for determining best PIO mode for an IDE drive. | ||
208 | * Most of this stuff originally lived in cmd640.c, and changes to the | ||
209 | * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid | ||
210 | * breaking the fragile cmd640.c support. | ||
211 | */ | ||
212 | |||
213 | /* | ||
214 | * Black list. Some drives incorrectly report their maximal PIO mode, | ||
215 | * at least in respect to CMD640. Here we keep info on some known drives. | ||
216 | */ | ||
217 | static struct ide_pio_info { | ||
218 | const char *name; | ||
219 | int pio; | ||
220 | } ide_pio_blacklist [] = { | ||
221 | /* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ | ||
222 | { "Conner Peripherals 540MB - CFS540A", 3 }, | ||
223 | |||
224 | { "WDC AC2700", 3 }, | ||
225 | { "WDC AC2540", 3 }, | ||
226 | { "WDC AC2420", 3 }, | ||
227 | { "WDC AC2340", 3 }, | ||
228 | { "WDC AC2250", 0 }, | ||
229 | { "WDC AC2200", 0 }, | ||
230 | { "WDC AC21200", 4 }, | ||
231 | { "WDC AC2120", 0 }, | ||
232 | { "WDC AC2850", 3 }, | ||
233 | { "WDC AC1270", 3 }, | ||
234 | { "WDC AC1170", 1 }, | ||
235 | { "WDC AC1210", 1 }, | ||
236 | { "WDC AC280", 0 }, | ||
237 | /* { "WDC AC21000", 4 }, */ | ||
238 | { "WDC AC31000", 3 }, | ||
239 | { "WDC AC31200", 3 }, | ||
240 | /* { "WDC AC31600", 4 }, */ | ||
241 | |||
242 | { "Maxtor 7131 AT", 1 }, | ||
243 | { "Maxtor 7171 AT", 1 }, | ||
244 | { "Maxtor 7213 AT", 1 }, | ||
245 | { "Maxtor 7245 AT", 1 }, | ||
246 | { "Maxtor 7345 AT", 1 }, | ||
247 | { "Maxtor 7546 AT", 3 }, | ||
248 | { "Maxtor 7540 AV", 3 }, | ||
249 | |||
250 | { "SAMSUNG SHD-3121A", 1 }, | ||
251 | { "SAMSUNG SHD-3122A", 1 }, | ||
252 | { "SAMSUNG SHD-3172A", 1 }, | ||
253 | |||
254 | /* { "ST51080A", 4 }, | ||
255 | * { "ST51270A", 4 }, | ||
256 | * { "ST31220A", 4 }, | ||
257 | * { "ST31640A", 4 }, | ||
258 | * { "ST32140A", 4 }, | ||
259 | * { "ST3780A", 4 }, | ||
260 | */ | ||
261 | { "ST5660A", 3 }, | ||
262 | { "ST3660A", 3 }, | ||
263 | { "ST3630A", 3 }, | ||
264 | { "ST3655A", 3 }, | ||
265 | { "ST3391A", 3 }, | ||
266 | { "ST3390A", 1 }, | ||
267 | { "ST3600A", 1 }, | ||
268 | { "ST3290A", 0 }, | ||
269 | { "ST3144A", 0 }, | ||
270 | { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ | ||
271 | /* drive) according to Seagates FIND-ATA program */ | ||
272 | |||
273 | { "QUANTUM ELS127A", 0 }, | ||
274 | { "QUANTUM ELS170A", 0 }, | ||
275 | { "QUANTUM LPS240A", 0 }, | ||
276 | { "QUANTUM LPS210A", 3 }, | ||
277 | { "QUANTUM LPS270A", 3 }, | ||
278 | { "QUANTUM LPS365A", 3 }, | ||
279 | { "QUANTUM LPS540A", 3 }, | ||
280 | { "QUANTUM LIGHTNING 540A", 3 }, | ||
281 | { "QUANTUM LIGHTNING 730A", 3 }, | ||
282 | |||
283 | { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ | ||
284 | { "QUANTUM FIREBALL_640", 3 }, | ||
285 | { "QUANTUM FIREBALL_1080", 3 }, | ||
286 | { "QUANTUM FIREBALL_1280", 3 }, | ||
287 | { NULL, 0 } | ||
288 | }; | ||
289 | |||
290 | /** | ||
291 | * ide_scan_pio_blacklist - check for a blacklisted drive | ||
292 | * @model: Drive model string | ||
293 | * | ||
294 | * This routine searches the ide_pio_blacklist for an entry | ||
295 | * matching the start/whole of the supplied model name. | ||
296 | * | ||
297 | * Returns -1 if no match found. | ||
298 | * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. | ||
299 | */ | ||
300 | |||
301 | static int ide_scan_pio_blacklist (char *model) | ||
302 | { | ||
303 | struct ide_pio_info *p; | ||
304 | |||
305 | for (p = ide_pio_blacklist; p->name != NULL; p++) { | ||
306 | if (strncmp(p->name, model, strlen(p->name)) == 0) | ||
307 | return p->pio; | ||
308 | } | ||
309 | return -1; | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * ide_get_best_pio_mode - get PIO mode from drive | ||
314 | * @driver: drive to consider | ||
315 | * @mode_wanted: preferred mode | ||
316 | * @max_mode: highest allowed | ||
317 | * @d: pio data | ||
318 | * | ||
319 | * This routine returns the recommended PIO settings for a given drive, | ||
320 | * based on the drive->id information and the ide_pio_blacklist[]. | ||
321 | * This is used by most chipset support modules when "auto-tuning". | ||
322 | * | ||
323 | * Drive PIO mode auto selection | ||
324 | */ | ||
325 | |||
326 | u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_pio_data_t *d) | ||
327 | { | ||
328 | int pio_mode; | ||
329 | int cycle_time = 0; | ||
330 | int use_iordy = 0; | ||
331 | struct hd_driveid* id = drive->id; | ||
332 | int overridden = 0; | ||
333 | int blacklisted = 0; | ||
334 | |||
335 | if (mode_wanted != 255) { | ||
336 | pio_mode = mode_wanted; | ||
337 | } else if (!drive->id) { | ||
338 | pio_mode = 0; | ||
339 | } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { | ||
340 | overridden = 1; | ||
341 | blacklisted = 1; | ||
342 | use_iordy = (pio_mode > 2); | ||
343 | } else { | ||
344 | pio_mode = id->tPIO; | ||
345 | if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ | ||
346 | pio_mode = 2; | ||
347 | overridden = 1; | ||
348 | } | ||
349 | if (id->field_valid & 2) { /* drive implements ATA2? */ | ||
350 | if (id->capability & 8) { /* drive supports use_iordy? */ | ||
351 | use_iordy = 1; | ||
352 | cycle_time = id->eide_pio_iordy; | ||
353 | if (id->eide_pio_modes & 7) { | ||
354 | overridden = 0; | ||
355 | if (id->eide_pio_modes & 4) | ||
356 | pio_mode = 5; | ||
357 | else if (id->eide_pio_modes & 2) | ||
358 | pio_mode = 4; | ||
359 | else | ||
360 | pio_mode = 3; | ||
361 | } | ||
362 | } else { | ||
363 | cycle_time = id->eide_pio; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | #if 0 | ||
368 | if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); | ||
369 | #endif | ||
370 | |||
371 | /* | ||
372 | * Conservative "downgrade" for all pre-ATA2 drives | ||
373 | */ | ||
374 | if (pio_mode && pio_mode < 4) { | ||
375 | pio_mode--; | ||
376 | overridden = 1; | ||
377 | #if 0 | ||
378 | use_iordy = (pio_mode > 2); | ||
379 | #endif | ||
380 | if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) | ||
381 | cycle_time = 0; /* use standard timing */ | ||
382 | } | ||
383 | } | ||
384 | if (pio_mode > max_mode) { | ||
385 | pio_mode = max_mode; | ||
386 | cycle_time = 0; | ||
387 | } | ||
388 | if (d) { | ||
389 | d->pio_mode = pio_mode; | ||
390 | d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; | ||
391 | d->use_iordy = use_iordy; | ||
392 | d->overridden = overridden; | ||
393 | d->blacklisted = blacklisted; | ||
394 | } | ||
395 | return pio_mode; | ||
396 | } | ||
397 | |||
398 | EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); | ||
399 | |||
400 | /** | ||
401 | * ide_toggle_bounce - handle bounce buffering | ||
402 | * @drive: drive to update | ||
403 | * @on: on/off boolean | ||
404 | * | ||
405 | * Enable or disable bounce buffering for the device. Drives move | ||
406 | * between PIO and DMA and that changes the rules we need. | ||
407 | */ | ||
408 | |||
409 | void ide_toggle_bounce(ide_drive_t *drive, int on) | ||
410 | { | ||
411 | u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ | ||
412 | |||
413 | if (on && drive->media == ide_disk) { | ||
414 | if (!PCI_DMA_BUS_IS_PHYS) | ||
415 | addr = BLK_BOUNCE_ANY; | ||
416 | else if (HWIF(drive)->pci_dev) | ||
417 | addr = HWIF(drive)->pci_dev->dma_mask; | ||
418 | } | ||
419 | |||
420 | if (drive->queue) | ||
421 | blk_queue_bounce_limit(drive->queue, addr); | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * ide_set_xfer_rate - set transfer rate | ||
426 | * @drive: drive to set | ||
427 | * @speed: speed to attempt to set | ||
428 | * | ||
429 | * General helper for setting the speed of an IDE device. This | ||
430 | * function knows about user enforced limits from the configuration | ||
431 | * which speedproc() does not. High level drivers should never | ||
432 | * invoke speedproc() directly. | ||
433 | */ | ||
434 | |||
435 | int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) | ||
436 | { | ||
437 | #ifndef CONFIG_BLK_DEV_IDEDMA | ||
438 | rate = min(rate, (u8) XFER_PIO_4); | ||
439 | #endif | ||
440 | if(HWIF(drive)->speedproc) | ||
441 | return HWIF(drive)->speedproc(drive, rate); | ||
442 | else | ||
443 | return -1; | ||
444 | } | ||
445 | |||
446 | EXPORT_SYMBOL_GPL(ide_set_xfer_rate); | ||
447 | |||
448 | static void ide_dump_opcode(ide_drive_t *drive) | ||
449 | { | ||
450 | struct request *rq; | ||
451 | u8 opcode = 0; | ||
452 | int found = 0; | ||
453 | |||
454 | spin_lock(&ide_lock); | ||
455 | rq = NULL; | ||
456 | if (HWGROUP(drive)) | ||
457 | rq = HWGROUP(drive)->rq; | ||
458 | spin_unlock(&ide_lock); | ||
459 | if (!rq) | ||
460 | return; | ||
461 | if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { | ||
462 | char *args = rq->buffer; | ||
463 | if (args) { | ||
464 | opcode = args[0]; | ||
465 | found = 1; | ||
466 | } | ||
467 | } else if (rq->flags & REQ_DRIVE_TASKFILE) { | ||
468 | ide_task_t *args = rq->special; | ||
469 | if (args) { | ||
470 | task_struct_t *tf = (task_struct_t *) args->tfRegister; | ||
471 | opcode = tf->command; | ||
472 | found = 1; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | printk("ide: failed opcode was: "); | ||
477 | if (!found) | ||
478 | printk("unknown\n"); | ||
479 | else | ||
480 | printk("0x%02x\n", opcode); | ||
481 | } | ||
482 | |||
483 | static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) | ||
484 | { | ||
485 | ide_hwif_t *hwif = HWIF(drive); | ||
486 | unsigned long flags; | ||
487 | u8 err = 0; | ||
488 | |||
489 | local_irq_set(flags); | ||
490 | printk("%s: %s: status=0x%02x", drive->name, msg, stat); | ||
491 | printk(" { "); | ||
492 | if (stat & BUSY_STAT) | ||
493 | printk("Busy "); | ||
494 | else { | ||
495 | if (stat & READY_STAT) printk("DriveReady "); | ||
496 | if (stat & WRERR_STAT) printk("DeviceFault "); | ||
497 | if (stat & SEEK_STAT) printk("SeekComplete "); | ||
498 | if (stat & DRQ_STAT) printk("DataRequest "); | ||
499 | if (stat & ECC_STAT) printk("CorrectedError "); | ||
500 | if (stat & INDEX_STAT) printk("Index "); | ||
501 | if (stat & ERR_STAT) printk("Error "); | ||
502 | } | ||
503 | printk("}"); | ||
504 | printk("\n"); | ||
505 | if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { | ||
506 | err = hwif->INB(IDE_ERROR_REG); | ||
507 | printk("%s: %s: error=0x%02x", drive->name, msg, err); | ||
508 | printk(" { "); | ||
509 | if (err & ABRT_ERR) printk("DriveStatusError "); | ||
510 | if (err & ICRC_ERR) | ||
511 | printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector"); | ||
512 | if (err & ECC_ERR) printk("UncorrectableError "); | ||
513 | if (err & ID_ERR) printk("SectorIdNotFound "); | ||
514 | if (err & TRK0_ERR) printk("TrackZeroNotFound "); | ||
515 | if (err & MARK_ERR) printk("AddrMarkNotFound "); | ||
516 | printk("}"); | ||
517 | if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || | ||
518 | (err & (ECC_ERR|ID_ERR|MARK_ERR))) { | ||
519 | if (drive->addressing == 1) { | ||
520 | __u64 sectors = 0; | ||
521 | u32 low = 0, high = 0; | ||
522 | low = ide_read_24(drive); | ||
523 | hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); | ||
524 | high = ide_read_24(drive); | ||
525 | sectors = ((__u64)high << 24) | low; | ||
526 | printk(", LBAsect=%llu, high=%d, low=%d", | ||
527 | (unsigned long long) sectors, | ||
528 | high, low); | ||
529 | } else { | ||
530 | u8 cur = hwif->INB(IDE_SELECT_REG); | ||
531 | if (cur & 0x40) { /* using LBA? */ | ||
532 | printk(", LBAsect=%ld", (unsigned long) | ||
533 | ((cur&0xf)<<24) | ||
534 | |(hwif->INB(IDE_HCYL_REG)<<16) | ||
535 | |(hwif->INB(IDE_LCYL_REG)<<8) | ||
536 | | hwif->INB(IDE_SECTOR_REG)); | ||
537 | } else { | ||
538 | printk(", CHS=%d/%d/%d", | ||
539 | (hwif->INB(IDE_HCYL_REG)<<8) + | ||
540 | hwif->INB(IDE_LCYL_REG), | ||
541 | cur & 0xf, | ||
542 | hwif->INB(IDE_SECTOR_REG)); | ||
543 | } | ||
544 | } | ||
545 | if (HWGROUP(drive) && HWGROUP(drive)->rq) | ||
546 | printk(", sector=%llu", | ||
547 | (unsigned long long)HWGROUP(drive)->rq->sector); | ||
548 | } | ||
549 | } | ||
550 | printk("\n"); | ||
551 | ide_dump_opcode(drive); | ||
552 | local_irq_restore(flags); | ||
553 | return err; | ||
554 | } | ||
555 | |||
556 | /** | ||
557 | * ide_dump_atapi_status - print human readable atapi status | ||
558 | * @drive: drive that status applies to | ||
559 | * @msg: text message to print | ||
560 | * @stat: status byte to decode | ||
561 | * | ||
562 | * Error reporting, in human readable form (luxurious, but a memory hog). | ||
563 | */ | ||
564 | |||
565 | static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) | ||
566 | { | ||
567 | unsigned long flags; | ||
568 | |||
569 | atapi_status_t status; | ||
570 | atapi_error_t error; | ||
571 | |||
572 | status.all = stat; | ||
573 | error.all = 0; | ||
574 | local_irq_set(flags); | ||
575 | printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); | ||
576 | if (status.b.bsy) | ||
577 | printk("Busy "); | ||
578 | else { | ||
579 | if (status.b.drdy) printk("DriveReady "); | ||
580 | if (status.b.df) printk("DeviceFault "); | ||
581 | if (status.b.dsc) printk("SeekComplete "); | ||
582 | if (status.b.drq) printk("DataRequest "); | ||
583 | if (status.b.corr) printk("CorrectedError "); | ||
584 | if (status.b.idx) printk("Index "); | ||
585 | if (status.b.check) printk("Error "); | ||
586 | } | ||
587 | printk("}\n"); | ||
588 | if (status.b.check && !status.b.bsy) { | ||
589 | error.all = HWIF(drive)->INB(IDE_ERROR_REG); | ||
590 | printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all); | ||
591 | if (error.b.ili) printk("IllegalLengthIndication "); | ||
592 | if (error.b.eom) printk("EndOfMedia "); | ||
593 | if (error.b.abrt) printk("AbortedCommand "); | ||
594 | if (error.b.mcr) printk("MediaChangeRequested "); | ||
595 | if (error.b.sense_key) printk("LastFailedSense=0x%02x ", | ||
596 | error.b.sense_key); | ||
597 | printk("}\n"); | ||
598 | } | ||
599 | ide_dump_opcode(drive); | ||
600 | local_irq_restore(flags); | ||
601 | return error.all; | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * ide_dump_status - translate ATA/ATAPI error | ||
606 | * @drive: drive the error occured on | ||
607 | * @msg: information string | ||
608 | * @stat: status byte | ||
609 | * | ||
610 | * Error reporting, in human readable form (luxurious, but a memory hog). | ||
611 | * Combines the drive name, message and status byte to provide a | ||
612 | * user understandable explanation of the device error. | ||
613 | */ | ||
614 | |||
615 | u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) | ||
616 | { | ||
617 | if (drive->media == ide_disk) | ||
618 | return ide_dump_ata_status(drive, msg, stat); | ||
619 | return ide_dump_atapi_status(drive, msg, stat); | ||
620 | } | ||
621 | |||
622 | EXPORT_SYMBOL(ide_dump_status); | ||