Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #include <linux/types.h> |
2 | #include <linux/string.h> | |
3 | #include <linux/kernel.h> | |
1da177e4 | 4 | #include <linux/interrupt.h> |
1da177e4 LT |
5 | #include <linux/hdreg.h> |
6 | #include <linux/ide.h> | |
7 | #include <linux/bitops.h> | |
8 | ||
3ab7efe8 BZ |
9 | static const char *udma_str[] = |
10 | { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", | |
11 | "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; | |
12 | static const char *mwdma_str[] = | |
13 | { "MWDMA0", "MWDMA1", "MWDMA2" }; | |
14 | static const char *swdma_str[] = | |
15 | { "SWDMA0", "SWDMA1", "SWDMA2" }; | |
16 | static const char *pio_str[] = | |
17 | { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; | |
1da177e4 LT |
18 | |
19 | /** | |
20 | * ide_xfer_verbose - return IDE mode names | |
3ab7efe8 | 21 | * @mode: transfer mode |
1da177e4 LT |
22 | * |
23 | * Returns a constant string giving the name of the mode | |
24 | * requested. | |
25 | */ | |
26 | ||
3ab7efe8 | 27 | const char *ide_xfer_verbose(u8 mode) |
1da177e4 | 28 | { |
3ab7efe8 BZ |
29 | 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; | |
1da177e4 LT |
46 | } |
47 | ||
48 | EXPORT_SYMBOL(ide_xfer_verbose); | |
49 | ||
50 | /** | |
2d5eaa6d BZ |
51 | * ide_rate_filter - filter transfer mode |
52 | * @drive: IDE device | |
1da177e4 LT |
53 | * @speed: desired speed |
54 | * | |
2d5eaa6d | 55 | * Given the available transfer modes this function returns |
1da177e4 | 56 | * the best available speed at or below the speed requested. |
2d5eaa6d | 57 | * |
7670df73 | 58 | * TODO: check device PIO capabilities |
1da177e4 LT |
59 | */ |
60 | ||
f212ff28 | 61 | static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) |
1da177e4 | 62 | { |
2d5eaa6d | 63 | ide_hwif_t *hwif = drive->hwif; |
7670df73 | 64 | u8 mode = ide_find_dma_mode(drive, speed); |
2d5eaa6d | 65 | |
7670df73 BZ |
66 | 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; | |
71 | } | |
1da177e4 | 72 | |
eb63963a | 73 | /* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ |
1da177e4 | 74 | |
2d5eaa6d | 75 | return min(speed, mode); |
1da177e4 LT |
76 | } |
77 | ||
1da177e4 LT |
78 | /** |
79 | * ide_get_best_pio_mode - get PIO mode from drive | |
81d368e0 | 80 | * @drive: drive to consider |
1da177e4 | 81 | * @mode_wanted: preferred mode |
81d368e0 | 82 | * @max_mode: highest allowed mode |
1da177e4 LT |
83 | * |
84 | * This routine returns the recommended PIO settings for a given drive, | |
85 | * based on the drive->id information and the ide_pio_blacklist[]. | |
1da177e4 | 86 | * |
81d368e0 SS |
87 | * 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". | |
1da177e4 LT |
89 | */ |
90 | ||
2134758d | 91 | u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) |
1da177e4 LT |
92 | { |
93 | int pio_mode; | |
1da177e4 LT |
94 | struct hd_driveid* id = drive->id; |
95 | int overridden = 0; | |
1da177e4 | 96 | |
6a824c92 BZ |
97 | if (mode_wanted != 255) |
98 | return min_t(u8, mode_wanted, max_mode); | |
99 | ||
100 | if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 && | |
101 | (pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { | |
342cdb6d | 102 | printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); |
1da177e4 LT |
103 | } else { |
104 | pio_mode = id->tPIO; | |
105 | if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ | |
106 | pio_mode = 2; | |
107 | overridden = 1; | |
108 | } | |
109 | if (id->field_valid & 2) { /* drive implements ATA2? */ | |
2229833c | 110 | if (id->capability & 8) { /* IORDY supported? */ |
1da177e4 LT |
111 | if (id->eide_pio_modes & 7) { |
112 | overridden = 0; | |
113 | if (id->eide_pio_modes & 4) | |
114 | pio_mode = 5; | |
115 | else if (id->eide_pio_modes & 2) | |
116 | pio_mode = 4; | |
117 | else | |
118 | pio_mode = 3; | |
119 | } | |
1da177e4 LT |
120 | } |
121 | } | |
122 | ||
342cdb6d BZ |
123 | if (overridden) |
124 | printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", | |
125 | drive->name); | |
1da177e4 | 126 | } |
7dd00083 BZ |
127 | |
128 | if (pio_mode > max_mode) | |
1da177e4 | 129 | pio_mode = max_mode; |
7dd00083 | 130 | |
1da177e4 LT |
131 | return pio_mode; |
132 | } | |
133 | ||
134 | EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); | |
135 | ||
26bcb879 BZ |
136 | /* req_pio == "255" for auto-tune */ |
137 | void ide_set_pio(ide_drive_t *drive, u8 req_pio) | |
138 | { | |
139 | ide_hwif_t *hwif = drive->hwif; | |
ac95beed | 140 | const struct ide_port_ops *port_ops = hwif->port_ops; |
26bcb879 BZ |
141 | u8 host_pio, pio; |
142 | ||
ac95beed | 143 | if (port_ops == NULL || port_ops->set_pio_mode == NULL || |
784506cb | 144 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) |
26bcb879 BZ |
145 | return; |
146 | ||
147 | BUG_ON(hwif->pio_mask == 0x00); | |
148 | ||
149 | host_pio = fls(hwif->pio_mask) - 1; | |
150 | ||
151 | pio = ide_get_best_pio_mode(drive, req_pio, host_pio); | |
152 | ||
153 | /* | |
154 | * TODO: | |
155 | * - report device max PIO mode | |
156 | * - check req_pio != 255 against device max PIO mode | |
157 | */ | |
158 | printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", | |
159 | drive->name, host_pio, req_pio, | |
160 | req_pio == 255 ? "(auto-tune)" : "", pio); | |
161 | ||
88b2b32b | 162 | (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); |
26bcb879 BZ |
163 | } |
164 | ||
165 | EXPORT_SYMBOL_GPL(ide_set_pio); | |
166 | ||
1da177e4 LT |
167 | /** |
168 | * ide_toggle_bounce - handle bounce buffering | |
169 | * @drive: drive to update | |
170 | * @on: on/off boolean | |
171 | * | |
172 | * Enable or disable bounce buffering for the device. Drives move | |
173 | * between PIO and DMA and that changes the rules we need. | |
174 | */ | |
175 | ||
176 | void ide_toggle_bounce(ide_drive_t *drive, int on) | |
177 | { | |
178 | u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ | |
179 | ||
6593178d JB |
180 | if (!PCI_DMA_BUS_IS_PHYS) { |
181 | addr = BLK_BOUNCE_ANY; | |
182 | } else if (on && drive->media == ide_disk) { | |
36501650 BZ |
183 | struct device *dev = drive->hwif->dev; |
184 | ||
185 | if (dev && dev->dma_mask) | |
186 | addr = *dev->dma_mask; | |
1da177e4 LT |
187 | } |
188 | ||
189 | if (drive->queue) | |
190 | blk_queue_bounce_limit(drive->queue, addr); | |
191 | } | |
192 | ||
88b2b32b BZ |
193 | int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) |
194 | { | |
195 | ide_hwif_t *hwif = drive->hwif; | |
ac95beed | 196 | const struct ide_port_ops *port_ops = hwif->port_ops; |
88b2b32b | 197 | |
784506cb BZ |
198 | if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) |
199 | return 0; | |
200 | ||
ac95beed | 201 | if (port_ops == NULL || port_ops->set_pio_mode == NULL) |
88b2b32b BZ |
202 | return -1; |
203 | ||
204 | /* | |
205 | * TODO: temporary hack for some legacy host drivers that didn't | |
206 | * set transfer mode on the device in ->set_pio_mode method... | |
207 | */ | |
ac95beed BZ |
208 | if (port_ops->set_dma_mode == NULL) { |
209 | port_ops->set_pio_mode(drive, mode - XFER_PIO_0); | |
88b2b32b BZ |
210 | return 0; |
211 | } | |
212 | ||
213 | if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { | |
214 | if (ide_config_drive_speed(drive, mode)) | |
215 | return -1; | |
ac95beed | 216 | port_ops->set_pio_mode(drive, mode - XFER_PIO_0); |
88b2b32b BZ |
217 | return 0; |
218 | } else { | |
ac95beed | 219 | port_ops->set_pio_mode(drive, mode - XFER_PIO_0); |
88b2b32b BZ |
220 | return ide_config_drive_speed(drive, mode); |
221 | } | |
222 | } | |
223 | ||
224 | int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) | |
225 | { | |
226 | ide_hwif_t *hwif = drive->hwif; | |
ac95beed | 227 | const struct ide_port_ops *port_ops = hwif->port_ops; |
88b2b32b | 228 | |
784506cb BZ |
229 | if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) |
230 | return 0; | |
231 | ||
ac95beed | 232 | if (port_ops == NULL || port_ops->set_dma_mode == NULL) |
88b2b32b BZ |
233 | return -1; |
234 | ||
235 | if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { | |
236 | if (ide_config_drive_speed(drive, mode)) | |
237 | return -1; | |
ac95beed | 238 | port_ops->set_dma_mode(drive, mode); |
88b2b32b BZ |
239 | return 0; |
240 | } else { | |
ac95beed | 241 | port_ops->set_dma_mode(drive, mode); |
88b2b32b BZ |
242 | return ide_config_drive_speed(drive, mode); |
243 | } | |
244 | } | |
245 | ||
246 | EXPORT_SYMBOL_GPL(ide_set_dma_mode); | |
247 | ||
1da177e4 LT |
248 | /** |
249 | * ide_set_xfer_rate - set transfer rate | |
250 | * @drive: drive to set | |
88b2b32b | 251 | * @rate: speed to attempt to set |
1da177e4 LT |
252 | * |
253 | * General helper for setting the speed of an IDE device. This | |
254 | * function knows about user enforced limits from the configuration | |
88b2b32b | 255 | * which ->set_pio_mode/->set_dma_mode does not. |
1da177e4 | 256 | */ |
88b2b32b | 257 | |
1da177e4 LT |
258 | int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) |
259 | { | |
f212ff28 | 260 | ide_hwif_t *hwif = drive->hwif; |
ac95beed | 261 | const struct ide_port_ops *port_ops = hwif->port_ops; |
f212ff28 | 262 | |
ac95beed | 263 | if (port_ops == NULL || port_ops->set_dma_mode == NULL || |
784506cb | 264 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) |
1da177e4 | 265 | return -1; |
f212ff28 BZ |
266 | |
267 | rate = ide_rate_filter(drive, rate); | |
268 | ||
88b2b32b BZ |
269 | if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) |
270 | return ide_set_pio_mode(drive, rate); | |
8f4dd2e4 | 271 | |
88b2b32b BZ |
272 | /* |
273 | * TODO: transfer modes 0x00-0x07 passed from the user-space are | |
274 | * currently handled here which needs fixing (please note that such | |
275 | * case could happen iff the transfer mode has already been set on | |
276 | * the device by ide-proc.c::set_xfer_rate()). | |
277 | */ | |
4db90a14 BZ |
278 | if (rate < XFER_PIO_0) { |
279 | if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE) | |
280 | return ide_set_dma_mode(drive, rate); | |
281 | else | |
282 | return ide_config_drive_speed(drive, rate); | |
283 | } | |
8f4dd2e4 | 284 | |
88b2b32b | 285 | return ide_set_dma_mode(drive, rate); |
1da177e4 LT |
286 | } |
287 | ||
1da177e4 LT |
288 | static void ide_dump_opcode(ide_drive_t *drive) |
289 | { | |
290 | struct request *rq; | |
7267c337 | 291 | ide_task_t *task = NULL; |
1da177e4 LT |
292 | |
293 | spin_lock(&ide_lock); | |
294 | rq = NULL; | |
295 | if (HWGROUP(drive)) | |
296 | rq = HWGROUP(drive)->rq; | |
297 | spin_unlock(&ide_lock); | |
298 | if (!rq) | |
299 | return; | |
7267c337 BZ |
300 | |
301 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) | |
302 | task = rq->special; | |
1da177e4 LT |
303 | |
304 | printk("ide: failed opcode was: "); | |
7267c337 BZ |
305 | if (task == NULL) |
306 | printk(KERN_CONT "unknown\n"); | |
1da177e4 | 307 | else |
7267c337 | 308 | printk(KERN_CONT "0x%02x\n", task->tf.command); |
1da177e4 LT |
309 | } |
310 | ||
a501633c | 311 | u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48) |
c2b57cdc BZ |
312 | { |
313 | u32 high, low; | |
314 | ||
315 | if (lba48) | |
316 | high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) | | |
317 | tf->hob_lbal; | |
318 | else | |
319 | high = tf->device & 0xf; | |
320 | low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; | |
321 | ||
322 | return ((u64)high << 24) | low; | |
323 | } | |
a501633c | 324 | EXPORT_SYMBOL_GPL(ide_get_lba_addr); |
c2b57cdc BZ |
325 | |
326 | static void ide_dump_sector(ide_drive_t *drive) | |
327 | { | |
328 | ide_task_t task; | |
329 | struct ide_taskfile *tf = &task.tf; | |
330 | int lba48 = (drive->addressing == 1) ? 1 : 0; | |
331 | ||
332 | memset(&task, 0, sizeof(task)); | |
333 | if (lba48) | |
334 | task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA | | |
335 | IDE_TFLAG_LBA48; | |
336 | else | |
337 | task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; | |
338 | ||
94cd5b62 | 339 | drive->hwif->tf_read(drive, &task); |
c2b57cdc BZ |
340 | |
341 | if (lba48 || (tf->device & ATA_LBA)) | |
1c904fcf AM |
342 | printk(", LBAsect=%llu", |
343 | (unsigned long long)ide_get_lba_addr(tf, lba48)); | |
c2b57cdc BZ |
344 | else |
345 | printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, | |
346 | tf->device & 0xf, tf->lbal); | |
347 | } | |
348 | ||
e62925dd | 349 | static void ide_dump_ata_error(ide_drive_t *drive, u8 err) |
1da177e4 | 350 | { |
e62925dd BZ |
351 | printk("{ "); |
352 | if (err & ABRT_ERR) printk("DriveStatusError "); | |
353 | if (err & ICRC_ERR) | |
354 | printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); | |
355 | if (err & ECC_ERR) printk("UncorrectableError "); | |
356 | if (err & ID_ERR) printk("SectorIdNotFound "); | |
357 | if (err & TRK0_ERR) printk("TrackZeroNotFound "); | |
358 | if (err & MARK_ERR) printk("AddrMarkNotFound "); | |
359 | printk("}"); | |
360 | if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || | |
361 | (err & (ECC_ERR|ID_ERR|MARK_ERR))) { | |
362 | ide_dump_sector(drive); | |
363 | if (HWGROUP(drive) && HWGROUP(drive)->rq) | |
364 | printk(", sector=%llu", | |
365 | (unsigned long long)HWGROUP(drive)->rq->sector); | |
1da177e4 | 366 | } |
e62925dd BZ |
367 | printk("\n"); |
368 | } | |
369 | ||
370 | static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) | |
371 | { | |
372 | printk("{ "); | |
373 | if (err & ILI_ERR) printk("IllegalLengthIndication "); | |
374 | if (err & EOM_ERR) printk("EndOfMedia "); | |
375 | if (err & ABRT_ERR) printk("AbortedCommand "); | |
376 | if (err & MCR_ERR) printk("MediaChangeRequested "); | |
377 | if (err & LFS_ERR) printk("LastFailedSense=0x%02x ", | |
378 | (err & LFS_ERR) >> 4); | |
13bbbf28 | 379 | printk("}\n"); |
1da177e4 LT |
380 | } |
381 | ||
382 | /** | |
e62925dd | 383 | * ide_dump_status - translate ATA/ATAPI error |
1da177e4 LT |
384 | * @drive: drive that status applies to |
385 | * @msg: text message to print | |
386 | * @stat: status byte to decode | |
387 | * | |
388 | * Error reporting, in human readable form (luxurious, but a memory hog). | |
e62925dd BZ |
389 | * Combines the drive name, message and status byte to provide a |
390 | * user understandable explanation of the device error. | |
1da177e4 LT |
391 | */ |
392 | ||
e62925dd | 393 | u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) |
1da177e4 LT |
394 | { |
395 | unsigned long flags; | |
0e38a66a | 396 | u8 err = 0; |
1da177e4 | 397 | |
3d1c1cc9 | 398 | local_irq_save(flags); |
1da177e4 | 399 | printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); |
22c525b9 | 400 | if (stat & BUSY_STAT) |
1da177e4 LT |
401 | printk("Busy "); |
402 | else { | |
22c525b9 BZ |
403 | if (stat & READY_STAT) printk("DriveReady "); |
404 | if (stat & WRERR_STAT) printk("DeviceFault "); | |
405 | if (stat & SEEK_STAT) printk("SeekComplete "); | |
406 | if (stat & DRQ_STAT) printk("DataRequest "); | |
407 | if (stat & ECC_STAT) printk("CorrectedError "); | |
408 | if (stat & INDEX_STAT) printk("Index "); | |
409 | if (stat & ERR_STAT) printk("Error "); | |
1da177e4 LT |
410 | } |
411 | printk("}\n"); | |
22c525b9 | 412 | if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { |
64a57fe4 | 413 | err = ide_read_error(drive); |
e62925dd BZ |
414 | printk("%s: %s: error=0x%02x ", drive->name, msg, err); |
415 | if (drive->media == ide_disk) | |
416 | ide_dump_ata_error(drive, err); | |
417 | else | |
418 | ide_dump_atapi_error(drive, err); | |
1da177e4 LT |
419 | } |
420 | ide_dump_opcode(drive); | |
421 | local_irq_restore(flags); | |
0e38a66a | 422 | return err; |
1da177e4 LT |
423 | } |
424 | ||
1da177e4 | 425 | EXPORT_SYMBOL(ide_dump_status); |