blob: c5c37bfd8b09f3eb204d8e7dc2b0d73b93874e54 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#include <linux/types.h>
2#include <linux/string.h>
3#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/hdreg.h>
6#include <linux/ide.h>
7#include <linux/bitops.h>
8
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +01009static const char *udma_str[] =
10 { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
11 "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
12static const char *mwdma_str[] =
13 { "MWDMA0", "MWDMA1", "MWDMA2" };
14static const char *swdma_str[] =
15 { "SWDMA0", "SWDMA1", "SWDMA2" };
16static const char *pio_str[] =
17 { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
19/**
20 * ide_xfer_verbose - return IDE mode names
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +010021 * @mode: transfer mode
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 *
23 * Returns a constant string giving the name of the mode
24 * requested.
25 */
26
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +010027const char *ide_xfer_verbose(u8 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -070028{
Bartlomiej Zolnierkiewicz3ab7efe2007-12-12 23:31:58 +010029 const char *s;
30 u8 i = mode & 0xf;
31
32 if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
33 s = udma_str[i];
34 else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
35 s = mwdma_str[i];
36 else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
37 s = swdma_str[i];
38 else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
39 s = pio_str[i & 0x7];
40 else if (mode == XFER_PIO_SLOW)
41 s = "PIO SLOW";
42 else
43 s = "XFER ERROR";
44
45 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -070046}
47
48EXPORT_SYMBOL(ide_xfer_verbose);
49
50/**
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020051 * ide_rate_filter - filter transfer mode
52 * @drive: IDE device
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 * @speed: desired speed
54 *
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020055 * Given the available transfer modes this function returns
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 * the best available speed at or below the speed requested.
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020057 *
Bartlomiej Zolnierkiewicz7670df72007-10-11 23:53:59 +020058 * TODO: check device PIO capabilities
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 */
60
Bartlomiej Zolnierkiewiczf212ff22007-10-11 23:53:59 +020061static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062{
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020063 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz7670df72007-10-11 23:53:59 +020064 u8 mode = ide_find_dma_mode(drive, speed);
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020065
Bartlomiej Zolnierkiewicz7670df72007-10-11 23:53:59 +020066 if (mode == 0) {
67 if (hwif->pio_mask)
68 mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
69 else
70 mode = XFER_PIO_4;
Bartlomiej Zolnierkiewicz7f8f48a2007-05-10 00:01:10 +020071 }
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020072
Harvey Harrisoneb639632008-04-26 22:25:20 +020073/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Bartlomiej Zolnierkiewicz2d5eaa62007-05-10 00:01:08 +020075 return min(speed, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076}
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078/**
79 * ide_get_best_pio_mode - get PIO mode from drive
Sergei Shtylyov81d368e2007-03-03 17:48:53 +010080 * @drive: drive to consider
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 * @mode_wanted: preferred mode
Sergei Shtylyov81d368e2007-03-03 17:48:53 +010082 * @max_mode: highest allowed mode
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 *
84 * This routine returns the recommended PIO settings for a given drive,
85 * based on the drive->id information and the ide_pio_blacklist[].
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 *
Sergei Shtylyov81d368e2007-03-03 17:48:53 +010087 * Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
88 * This is used by most chipset support modules when "auto-tuning".
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 */
90
Bartlomiej Zolnierkiewicz21347582007-07-20 01:11:58 +020091u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +020093 u16 *id = drive->id;
94 int pio_mode = -1, overridden = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Bartlomiej Zolnierkiewicz6a824c92007-07-20 01:11:58 +020096 if (mode_wanted != 255)
97 return min_t(u8, mode_wanted, max_mode);
98
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +020099 if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
100 pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
101
102 if (pio_mode != -1) {
Bartlomiej Zolnierkiewicz342cdb62007-07-20 01:11:55 +0200103 printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 } else {
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200105 pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
107 pio_mode = 2;
108 overridden = 1;
109 }
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200110
111 if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
Bartlomiej Zolnierkiewicz48fb2682008-10-10 22:39:19 +0200112 if (ata_id_has_iordy(id)) {
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200113 if (id[ATA_ID_PIO_MODES] & 7) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 overridden = 0;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200115 if (id[ATA_ID_PIO_MODES] & 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 pio_mode = 5;
Bartlomiej Zolnierkiewicz4dde4492008-10-10 22:39:19 +0200117 else if (id[ATA_ID_PIO_MODES] & 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 pio_mode = 4;
119 else
120 pio_mode = 3;
121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 }
123 }
124
Bartlomiej Zolnierkiewicz342cdb62007-07-20 01:11:55 +0200125 if (overridden)
126 printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
127 drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 }
Bartlomiej Zolnierkiewicz7dd00082007-07-20 01:11:56 +0200129
130 if (pio_mode > max_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 pio_mode = max_mode;
Bartlomiej Zolnierkiewicz7dd00082007-07-20 01:11:56 +0200132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 return pio_mode;
134}
135
136EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
137
Bartlomiej Zolnierkiewicz26bcb872007-10-11 23:54:00 +0200138/* req_pio == "255" for auto-tune */
139void ide_set_pio(ide_drive_t *drive, u8 req_pio)
140{
141 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200142 const struct ide_port_ops *port_ops = hwif->port_ops;
Bartlomiej Zolnierkiewicz26bcb872007-10-11 23:54:00 +0200143 u8 host_pio, pio;
144
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200145 if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
Bartlomiej Zolnierkiewicz784506c2008-04-26 17:36:43 +0200146 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
Bartlomiej Zolnierkiewicz26bcb872007-10-11 23:54:00 +0200147 return;
148
149 BUG_ON(hwif->pio_mask == 0x00);
150
151 host_pio = fls(hwif->pio_mask) - 1;
152
153 pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
154
155 /*
156 * TODO:
157 * - report device max PIO mode
158 * - check req_pio != 255 against device max PIO mode
159 */
160 printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
161 drive->name, host_pio, req_pio,
162 req_pio == 255 ? "(auto-tune)" : "", pio);
163
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200164 (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
Bartlomiej Zolnierkiewicz26bcb872007-10-11 23:54:00 +0200165}
166
167EXPORT_SYMBOL_GPL(ide_set_pio);
168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169/**
170 * ide_toggle_bounce - handle bounce buffering
171 * @drive: drive to update
172 * @on: on/off boolean
173 *
174 * Enable or disable bounce buffering for the device. Drives move
175 * between PIO and DMA and that changes the rules we need.
176 */
177
178void ide_toggle_bounce(ide_drive_t *drive, int on)
179{
180 u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
181
James Bottomley65931782005-11-18 23:13:33 +0100182 if (!PCI_DMA_BUS_IS_PHYS) {
183 addr = BLK_BOUNCE_ANY;
184 } else if (on && drive->media == ide_disk) {
Bartlomiej Zolnierkiewicz36501652008-02-01 23:09:31 +0100185 struct device *dev = drive->hwif->dev;
186
187 if (dev && dev->dma_mask)
188 addr = *dev->dma_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 }
190
191 if (drive->queue)
192 blk_queue_bounce_limit(drive->queue, addr);
193}
194
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200195int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
196{
197 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200198 const struct ide_port_ops *port_ops = hwif->port_ops;
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200199
Bartlomiej Zolnierkiewicz784506c2008-04-26 17:36:43 +0200200 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
201 return 0;
202
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200203 if (port_ops == NULL || port_ops->set_pio_mode == NULL)
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200204 return -1;
205
206 /*
207 * TODO: temporary hack for some legacy host drivers that didn't
208 * set transfer mode on the device in ->set_pio_mode method...
209 */
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200210 if (port_ops->set_dma_mode == NULL) {
211 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200212 return 0;
213 }
214
215 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
216 if (ide_config_drive_speed(drive, mode))
217 return -1;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200218 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200219 return 0;
220 } else {
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200221 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200222 return ide_config_drive_speed(drive, mode);
223 }
224}
225
226int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
227{
228 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200229 const struct ide_port_ops *port_ops = hwif->port_ops;
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200230
Bartlomiej Zolnierkiewicz784506c2008-04-26 17:36:43 +0200231 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
232 return 0;
233
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200234 if (port_ops == NULL || port_ops->set_dma_mode == NULL)
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200235 return -1;
236
237 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
238 if (ide_config_drive_speed(drive, mode))
239 return -1;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200240 port_ops->set_dma_mode(drive, mode);
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200241 return 0;
242 } else {
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200243 port_ops->set_dma_mode(drive, mode);
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200244 return ide_config_drive_speed(drive, mode);
245 }
246}
247
248EXPORT_SYMBOL_GPL(ide_set_dma_mode);
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250/**
251 * ide_set_xfer_rate - set transfer rate
252 * @drive: drive to set
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200253 * @rate: speed to attempt to set
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 *
255 * General helper for setting the speed of an IDE device. This
256 * function knows about user enforced limits from the configuration
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200257 * which ->set_pio_mode/->set_dma_mode does not.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 */
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
261{
Bartlomiej Zolnierkiewiczf212ff22007-10-11 23:53:59 +0200262 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200263 const struct ide_port_ops *port_ops = hwif->port_ops;
Bartlomiej Zolnierkiewiczf212ff22007-10-11 23:53:59 +0200264
Bartlomiej Zolnierkiewiczac95bee2008-04-26 22:25:14 +0200265 if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
Bartlomiej Zolnierkiewicz784506c2008-04-26 17:36:43 +0200266 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 return -1;
Bartlomiej Zolnierkiewiczf212ff22007-10-11 23:53:59 +0200268
269 rate = ide_rate_filter(drive, rate);
270
Bartlomiej Zolnierkiewicz3b2a5c72008-07-23 19:55:56 +0200271 BUG_ON(rate < XFER_PIO_0);
272
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200273 if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
274 return ide_set_pio_mode(drive, rate);
Bartlomiej Zolnierkiewicz8f4dd2e2007-10-11 23:54:02 +0200275
Bartlomiej Zolnierkiewicz88b2b322007-10-13 17:47:51 +0200276 return ide_set_dma_mode(drive, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277}
278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279static void ide_dump_opcode(ide_drive_t *drive)
280{
281 struct request *rq;
Bartlomiej Zolnierkiewicz7267c332008-01-26 20:13:13 +0100282 ide_task_t *task = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 spin_lock(&ide_lock);
285 rq = NULL;
286 if (HWGROUP(drive))
287 rq = HWGROUP(drive)->rq;
288 spin_unlock(&ide_lock);
289 if (!rq)
290 return;
Bartlomiej Zolnierkiewicz7267c332008-01-26 20:13:13 +0100291
292 if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
293 task = rq->special;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
295 printk("ide: failed opcode was: ");
Bartlomiej Zolnierkiewicz7267c332008-01-26 20:13:13 +0100296 if (task == NULL)
297 printk(KERN_CONT "unknown\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 else
Bartlomiej Zolnierkiewicz7267c332008-01-26 20:13:13 +0100299 printk(KERN_CONT "0x%02x\n", task->tf.command);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100302u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
Bartlomiej Zolnierkiewiczc2b57cd2008-01-25 22:17:17 +0100303{
304 u32 high, low;
305
306 if (lba48)
307 high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
308 tf->hob_lbal;
309 else
310 high = tf->device & 0xf;
311 low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
312
313 return ((u64)high << 24) | low;
314}
Bartlomiej Zolnierkiewicza5016332008-01-25 22:17:17 +0100315EXPORT_SYMBOL_GPL(ide_get_lba_addr);
Bartlomiej Zolnierkiewiczc2b57cd2008-01-25 22:17:17 +0100316
317static void ide_dump_sector(ide_drive_t *drive)
318{
319 ide_task_t task;
320 struct ide_taskfile *tf = &task.tf;
321 int lba48 = (drive->addressing == 1) ? 1 : 0;
322
323 memset(&task, 0, sizeof(task));
324 if (lba48)
325 task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
326 IDE_TFLAG_LBA48;
327 else
328 task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
329
Bartlomiej Zolnierkiewicz374e0422008-07-23 19:55:56 +0200330 drive->hwif->tp_ops->tf_read(drive, &task);
Bartlomiej Zolnierkiewiczc2b57cd2008-01-25 22:17:17 +0100331
332 if (lba48 || (tf->device & ATA_LBA))
Andrew Morton1c904fc2008-01-25 22:17:17 +0100333 printk(", LBAsect=%llu",
334 (unsigned long long)ide_get_lba_addr(tf, lba48));
Bartlomiej Zolnierkiewiczc2b57cd2008-01-25 22:17:17 +0100335 else
336 printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
337 tf->device & 0xf, tf->lbal);
338}
339
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100340static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100342 printk("{ ");
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200343 if (err & ATA_ABORTED) printk("DriveStatusError ");
344 if (err & ATA_ICRC)
345 printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
346 if (err & ATA_UNC) printk("UncorrectableError ");
347 if (err & ATA_IDNF) printk("SectorIdNotFound ");
348 if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
349 if (err & ATA_AMNF) printk("AddrMarkNotFound ");
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100350 printk("}");
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200351 if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
352 (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100353 ide_dump_sector(drive);
354 if (HWGROUP(drive) && HWGROUP(drive)->rq)
355 printk(", sector=%llu",
356 (unsigned long long)HWGROUP(drive)->rq->sector);
357 }
358 printk("\n");
359}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100361static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
362{
363 printk("{ ");
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200364 if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
365 if (err & ATAPI_EOM) printk("EndOfMedia ");
366 if (err & ATA_ABORTED) printk("AbortedCommand ");
367 if (err & ATA_MCR) printk("MediaChangeRequested ");
368 if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
369 (err & ATAPI_LFS) >> 4);
Denis Vlasenko13bbbf22005-07-03 17:09:13 +0200370 printk("}\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371}
372
373/**
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100374 * ide_dump_status - translate ATA/ATAPI error
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 * @drive: drive that status applies to
376 * @msg: text message to print
377 * @stat: status byte to decode
378 *
379 * Error reporting, in human readable form (luxurious, but a memory hog).
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100380 * Combines the drive name, message and status byte to provide a
381 * user understandable explanation of the device error.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 */
383
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100384u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
386 unsigned long flags;
Bartlomiej Zolnierkiewicz0e38a662008-01-25 22:17:12 +0100387 u8 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Ingo Molnar3d1c1cc2006-06-26 00:26:17 -0700389 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200391 if (stat & ATA_BUSY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 printk("Busy ");
393 else {
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200394 if (stat & ATA_DRDY) printk("DriveReady ");
395 if (stat & ATA_DF) printk("DeviceFault ");
396 if (stat & ATA_DSC) printk("SeekComplete ");
397 if (stat & ATA_DRQ) printk("DataRequest ");
398 if (stat & ATA_CORR) printk("CorrectedError ");
399 if (stat & ATA_IDX) printk("Index ");
400 if (stat & ATA_ERR) printk("Error ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402 printk("}\n");
Bartlomiej Zolnierkiewicz3a7d2482008-10-10 22:39:21 +0200403 if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
Bartlomiej Zolnierkiewicz64a57fe2008-02-06 02:57:51 +0100404 err = ide_read_error(drive);
Bartlomiej Zolnierkiewicze62925d2008-01-25 22:17:17 +0100405 printk("%s: %s: error=0x%02x ", drive->name, msg, err);
406 if (drive->media == ide_disk)
407 ide_dump_ata_error(drive, err);
408 else
409 ide_dump_atapi_error(drive, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411 ide_dump_opcode(drive);
412 local_irq_restore(flags);
Bartlomiej Zolnierkiewicz0e38a662008-01-25 22:17:12 +0100413 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416EXPORT_SYMBOL(ide_dump_status);