diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 238 |
1 files changed, 29 insertions, 209 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 772451600e4d..9dcf5aed92cb 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -44,8 +44,6 @@ | |||
44 | * inspiration from lots of linux users, esp. hamish@zot.apana.org.au | 44 | * inspiration from lots of linux users, esp. hamish@zot.apana.org.au |
45 | */ | 45 | */ |
46 | 46 | ||
47 | #define _IDE_C /* Tell ide.h it's really us */ | ||
48 | |||
49 | #include <linux/module.h> | 47 | #include <linux/module.h> |
50 | #include <linux/types.h> | 48 | #include <linux/types.h> |
51 | #include <linux/string.h> | 49 | #include <linux/string.h> |
@@ -58,6 +56,7 @@ | |||
58 | #include <linux/init.h> | 56 | #include <linux/init.h> |
59 | #include <linux/pci.h> | 57 | #include <linux/pci.h> |
60 | #include <linux/ide.h> | 58 | #include <linux/ide.h> |
59 | #include <linux/hdreg.h> | ||
61 | #include <linux/completion.h> | 60 | #include <linux/completion.h> |
62 | #include <linux/device.h> | 61 | #include <linux/device.h> |
63 | 62 | ||
@@ -97,8 +96,6 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) | |||
97 | hwif->name[2] = 'e'; | 96 | hwif->name[2] = 'e'; |
98 | hwif->name[3] = '0' + index; | 97 | hwif->name[3] = '0' + index; |
99 | 98 | ||
100 | hwif->bus_state = BUSSTATE_ON; | ||
101 | |||
102 | init_completion(&hwif->gendev_rel_comp); | 99 | init_completion(&hwif->gendev_rel_comp); |
103 | 100 | ||
104 | hwif->tp_ops = &default_tp_ops; | 101 | hwif->tp_ops = &default_tp_ops; |
@@ -119,7 +116,7 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | |||
119 | drive->media = ide_disk; | 116 | drive->media = ide_disk; |
120 | drive->select.all = (unit<<4)|0xa0; | 117 | drive->select.all = (unit<<4)|0xa0; |
121 | drive->hwif = hwif; | 118 | drive->hwif = hwif; |
122 | drive->ready_stat = READY_STAT; | 119 | drive->ready_stat = ATA_DRDY; |
123 | drive->bad_wstat = BAD_W_STAT; | 120 | drive->bad_wstat = BAD_W_STAT; |
124 | drive->special.b.recalibrate = 1; | 121 | drive->special.b.recalibrate = 1; |
125 | drive->special.b.set_geometry = 1; | 122 | drive->special.b.set_geometry = 1; |
@@ -253,42 +250,9 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) | |||
253 | 250 | ||
254 | DEFINE_MUTEX(ide_setting_mtx); | 251 | DEFINE_MUTEX(ide_setting_mtx); |
255 | 252 | ||
256 | EXPORT_SYMBOL_GPL(ide_setting_mtx); | 253 | ide_devset_get(io_32bit, io_32bit); |
257 | |||
258 | /** | ||
259 | * ide_spin_wait_hwgroup - wait for group | ||
260 | * @drive: drive in the group | ||
261 | * | ||
262 | * Wait for an IDE device group to go non busy and then return | ||
263 | * holding the ide_lock which guards the hwgroup->busy status | ||
264 | * and right to use it. | ||
265 | */ | ||
266 | 254 | ||
267 | int ide_spin_wait_hwgroup (ide_drive_t *drive) | 255 | static int set_io_32bit(ide_drive_t *drive, int arg) |
268 | { | ||
269 | ide_hwgroup_t *hwgroup = HWGROUP(drive); | ||
270 | unsigned long timeout = jiffies + (3 * HZ); | ||
271 | |||
272 | spin_lock_irq(&ide_lock); | ||
273 | |||
274 | while (hwgroup->busy) { | ||
275 | unsigned long lflags; | ||
276 | spin_unlock_irq(&ide_lock); | ||
277 | local_irq_set(lflags); | ||
278 | if (time_after(jiffies, timeout)) { | ||
279 | local_irq_restore(lflags); | ||
280 | printk(KERN_ERR "%s: channel busy\n", drive->name); | ||
281 | return -EBUSY; | ||
282 | } | ||
283 | local_irq_restore(lflags); | ||
284 | spin_lock_irq(&ide_lock); | ||
285 | } | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | EXPORT_SYMBOL(ide_spin_wait_hwgroup); | ||
290 | |||
291 | int set_io_32bit(ide_drive_t *drive, int arg) | ||
292 | { | 256 | { |
293 | if (drive->no_io_32bit) | 257 | if (drive->no_io_32bit) |
294 | return -EPERM; | 258 | return -EPERM; |
@@ -296,53 +260,39 @@ int set_io_32bit(ide_drive_t *drive, int arg) | |||
296 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) | 260 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) |
297 | return -EINVAL; | 261 | return -EINVAL; |
298 | 262 | ||
299 | if (ide_spin_wait_hwgroup(drive)) | ||
300 | return -EBUSY; | ||
301 | |||
302 | drive->io_32bit = arg; | 263 | drive->io_32bit = arg; |
303 | 264 | ||
304 | spin_unlock_irq(&ide_lock); | ||
305 | |||
306 | return 0; | 265 | return 0; |
307 | } | 266 | } |
308 | 267 | ||
268 | ide_devset_get(ksettings, keep_settings); | ||
269 | |||
309 | static int set_ksettings(ide_drive_t *drive, int arg) | 270 | static int set_ksettings(ide_drive_t *drive, int arg) |
310 | { | 271 | { |
311 | if (arg < 0 || arg > 1) | 272 | if (arg < 0 || arg > 1) |
312 | return -EINVAL; | 273 | return -EINVAL; |
313 | 274 | ||
314 | if (ide_spin_wait_hwgroup(drive)) | ||
315 | return -EBUSY; | ||
316 | drive->keep_settings = arg; | 275 | drive->keep_settings = arg; |
317 | spin_unlock_irq(&ide_lock); | ||
318 | 276 | ||
319 | return 0; | 277 | return 0; |
320 | } | 278 | } |
321 | 279 | ||
322 | int set_using_dma(ide_drive_t *drive, int arg) | 280 | ide_devset_get(using_dma, using_dma); |
281 | |||
282 | static int set_using_dma(ide_drive_t *drive, int arg) | ||
323 | { | 283 | { |
324 | #ifdef CONFIG_BLK_DEV_IDEDMA | 284 | #ifdef CONFIG_BLK_DEV_IDEDMA |
325 | ide_hwif_t *hwif = drive->hwif; | ||
326 | int err = -EPERM; | 285 | int err = -EPERM; |
327 | 286 | ||
328 | if (arg < 0 || arg > 1) | 287 | if (arg < 0 || arg > 1) |
329 | return -EINVAL; | 288 | return -EINVAL; |
330 | 289 | ||
331 | if (!drive->id || !(drive->id->capability & 1)) | 290 | if (ata_id_has_dma(drive->id) == 0) |
332 | goto out; | 291 | goto out; |
333 | 292 | ||
334 | if (hwif->dma_ops == NULL) | 293 | if (drive->hwif->dma_ops == NULL) |
335 | goto out; | 294 | goto out; |
336 | 295 | ||
337 | err = -EBUSY; | ||
338 | if (ide_spin_wait_hwgroup(drive)) | ||
339 | goto out; | ||
340 | /* | ||
341 | * set ->busy flag, unlock and let it ride | ||
342 | */ | ||
343 | hwif->hwgroup->busy = 1; | ||
344 | spin_unlock_irq(&ide_lock); | ||
345 | |||
346 | err = 0; | 296 | err = 0; |
347 | 297 | ||
348 | if (arg) { | 298 | if (arg) { |
@@ -351,12 +301,6 @@ int set_using_dma(ide_drive_t *drive, int arg) | |||
351 | } else | 301 | } else |
352 | ide_dma_off(drive); | 302 | ide_dma_off(drive); |
353 | 303 | ||
354 | /* | ||
355 | * lock, clear ->busy flag and unlock before leaving | ||
356 | */ | ||
357 | spin_lock_irq(&ide_lock); | ||
358 | hwif->hwgroup->busy = 0; | ||
359 | spin_unlock_irq(&ide_lock); | ||
360 | out: | 304 | out: |
361 | return err; | 305 | return err; |
362 | #else | 306 | #else |
@@ -367,7 +311,7 @@ out: | |||
367 | #endif | 311 | #endif |
368 | } | 312 | } |
369 | 313 | ||
370 | int set_pio_mode(ide_drive_t *drive, int arg) | 314 | static int set_pio_mode(ide_drive_t *drive, int arg) |
371 | { | 315 | { |
372 | struct request *rq; | 316 | struct request *rq; |
373 | ide_hwif_t *hwif = drive->hwif; | 317 | ide_hwif_t *hwif = drive->hwif; |
@@ -395,6 +339,8 @@ int set_pio_mode(ide_drive_t *drive, int arg) | |||
395 | return 0; | 339 | return 0; |
396 | } | 340 | } |
397 | 341 | ||
342 | ide_devset_get(unmaskirq, unmask); | ||
343 | |||
398 | static int set_unmaskirq(ide_drive_t *drive, int arg) | 344 | static int set_unmaskirq(ide_drive_t *drive, int arg) |
399 | { | 345 | { |
400 | if (drive->no_unmask) | 346 | if (drive->no_unmask) |
@@ -403,14 +349,20 @@ static int set_unmaskirq(ide_drive_t *drive, int arg) | |||
403 | if (arg < 0 || arg > 1) | 349 | if (arg < 0 || arg > 1) |
404 | return -EINVAL; | 350 | return -EINVAL; |
405 | 351 | ||
406 | if (ide_spin_wait_hwgroup(drive)) | ||
407 | return -EBUSY; | ||
408 | drive->unmask = arg; | 352 | drive->unmask = arg; |
409 | spin_unlock_irq(&ide_lock); | ||
410 | 353 | ||
411 | return 0; | 354 | return 0; |
412 | } | 355 | } |
413 | 356 | ||
357 | #define ide_gen_devset_rw(_name, _func) \ | ||
358 | __IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) | ||
359 | |||
360 | ide_gen_devset_rw(io_32bit, io_32bit); | ||
361 | ide_gen_devset_rw(keepsettings, ksettings); | ||
362 | ide_gen_devset_rw(unmaskirq, unmaskirq); | ||
363 | ide_gen_devset_rw(using_dma, using_dma); | ||
364 | __IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); | ||
365 | |||
414 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | 366 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) |
415 | { | 367 | { |
416 | ide_drive_t *drive = dev->driver_data; | 368 | ide_drive_t *drive = dev->driver_data; |
@@ -486,138 +438,6 @@ static int generic_ide_resume(struct device *dev) | |||
486 | return err; | 438 | return err; |
487 | } | 439 | } |
488 | 440 | ||
489 | static int generic_drive_reset(ide_drive_t *drive) | ||
490 | { | ||
491 | struct request *rq; | ||
492 | int ret = 0; | ||
493 | |||
494 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | ||
495 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
496 | rq->cmd_len = 1; | ||
497 | rq->cmd[0] = REQ_DRIVE_RESET; | ||
498 | rq->cmd_flags |= REQ_SOFTBARRIER; | ||
499 | if (blk_execute_rq(drive->queue, NULL, rq, 1)) | ||
500 | ret = rq->errors; | ||
501 | blk_put_request(rq); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, | ||
506 | unsigned int cmd, unsigned long arg) | ||
507 | { | ||
508 | unsigned long flags; | ||
509 | ide_driver_t *drv; | ||
510 | void __user *p = (void __user *)arg; | ||
511 | int err = 0, (*setfunc)(ide_drive_t *, int); | ||
512 | u8 *val; | ||
513 | |||
514 | switch (cmd) { | ||
515 | case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; | ||
516 | case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; | ||
517 | case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; | ||
518 | case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; | ||
519 | case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; | ||
520 | case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; | ||
521 | case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; | ||
522 | case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; | ||
523 | case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; | ||
524 | } | ||
525 | |||
526 | switch (cmd) { | ||
527 | case HDIO_OBSOLETE_IDENTITY: | ||
528 | case HDIO_GET_IDENTITY: | ||
529 | if (bdev != bdev->bd_contains) | ||
530 | return -EINVAL; | ||
531 | if (drive->id_read == 0) | ||
532 | return -ENOMSG; | ||
533 | if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) | ||
534 | return -EFAULT; | ||
535 | return 0; | ||
536 | |||
537 | case HDIO_GET_NICE: | ||
538 | return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | | ||
539 | drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | | ||
540 | drive->nice1 << IDE_NICE_1, | ||
541 | (long __user *) arg); | ||
542 | #ifdef CONFIG_IDE_TASK_IOCTL | ||
543 | case HDIO_DRIVE_TASKFILE: | ||
544 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | ||
545 | return -EACCES; | ||
546 | switch(drive->media) { | ||
547 | case ide_disk: | ||
548 | return ide_taskfile_ioctl(drive, cmd, arg); | ||
549 | default: | ||
550 | return -ENOMSG; | ||
551 | } | ||
552 | #endif /* CONFIG_IDE_TASK_IOCTL */ | ||
553 | |||
554 | case HDIO_DRIVE_CMD: | ||
555 | if (!capable(CAP_SYS_RAWIO)) | ||
556 | return -EACCES; | ||
557 | return ide_cmd_ioctl(drive, cmd, arg); | ||
558 | |||
559 | case HDIO_DRIVE_TASK: | ||
560 | if (!capable(CAP_SYS_RAWIO)) | ||
561 | return -EACCES; | ||
562 | return ide_task_ioctl(drive, cmd, arg); | ||
563 | case HDIO_SET_NICE: | ||
564 | if (!capable(CAP_SYS_ADMIN)) return -EACCES; | ||
565 | if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) | ||
566 | return -EPERM; | ||
567 | drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; | ||
568 | drv = *(ide_driver_t **)bdev->bd_disk->private_data; | ||
569 | if (drive->dsc_overlap && !drv->supports_dsc_overlap) { | ||
570 | drive->dsc_overlap = 0; | ||
571 | return -EPERM; | ||
572 | } | ||
573 | drive->nice1 = (arg >> IDE_NICE_1) & 1; | ||
574 | return 0; | ||
575 | case HDIO_DRIVE_RESET: | ||
576 | if (!capable(CAP_SYS_ADMIN)) | ||
577 | return -EACCES; | ||
578 | |||
579 | return generic_drive_reset(drive); | ||
580 | |||
581 | case HDIO_GET_BUSSTATE: | ||
582 | if (!capable(CAP_SYS_ADMIN)) | ||
583 | return -EACCES; | ||
584 | if (put_user(HWIF(drive)->bus_state, (long __user *)arg)) | ||
585 | return -EFAULT; | ||
586 | return 0; | ||
587 | |||
588 | case HDIO_SET_BUSSTATE: | ||
589 | if (!capable(CAP_SYS_ADMIN)) | ||
590 | return -EACCES; | ||
591 | return -EOPNOTSUPP; | ||
592 | default: | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | |||
596 | read_val: | ||
597 | mutex_lock(&ide_setting_mtx); | ||
598 | spin_lock_irqsave(&ide_lock, flags); | ||
599 | err = *val; | ||
600 | spin_unlock_irqrestore(&ide_lock, flags); | ||
601 | mutex_unlock(&ide_setting_mtx); | ||
602 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | ||
603 | |||
604 | set_val: | ||
605 | if (bdev != bdev->bd_contains) | ||
606 | err = -EINVAL; | ||
607 | else { | ||
608 | if (!capable(CAP_SYS_ADMIN)) | ||
609 | err = -EACCES; | ||
610 | else { | ||
611 | mutex_lock(&ide_setting_mtx); | ||
612 | err = setfunc(drive, arg); | ||
613 | mutex_unlock(&ide_setting_mtx); | ||
614 | } | ||
615 | } | ||
616 | return err; | ||
617 | } | ||
618 | |||
619 | EXPORT_SYMBOL(generic_ide_ioctl); | ||
620 | |||
621 | /** | 441 | /** |
622 | * ide_device_get - get an additional reference to a ide_drive_t | 442 | * ide_device_get - get an additional reference to a ide_drive_t |
623 | * @drive: device to get a reference to | 443 | * @drive: device to get a reference to |
@@ -710,21 +530,21 @@ static ssize_t model_show(struct device *dev, struct device_attribute *attr, | |||
710 | char *buf) | 530 | char *buf) |
711 | { | 531 | { |
712 | ide_drive_t *drive = to_ide_device(dev); | 532 | ide_drive_t *drive = to_ide_device(dev); |
713 | return sprintf(buf, "%s\n", drive->id->model); | 533 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); |
714 | } | 534 | } |
715 | 535 | ||
716 | static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, | 536 | static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, |
717 | char *buf) | 537 | char *buf) |
718 | { | 538 | { |
719 | ide_drive_t *drive = to_ide_device(dev); | 539 | ide_drive_t *drive = to_ide_device(dev); |
720 | return sprintf(buf, "%s\n", drive->id->fw_rev); | 540 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); |
721 | } | 541 | } |
722 | 542 | ||
723 | static ssize_t serial_show(struct device *dev, struct device_attribute *attr, | 543 | static ssize_t serial_show(struct device *dev, struct device_attribute *attr, |
724 | char *buf) | 544 | char *buf) |
725 | { | 545 | { |
726 | ide_drive_t *drive = to_ide_device(dev); | 546 | ide_drive_t *drive = to_ide_device(dev); |
727 | return sprintf(buf, "%s\n", drive->id->serial_no); | 547 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); |
728 | } | 548 | } |
729 | 549 | ||
730 | static struct device_attribute ide_dev_attrs[] = { | 550 | static struct device_attribute ide_dev_attrs[] = { |
@@ -841,7 +661,7 @@ MODULE_PARM_DESC(noprobe, "skip probing for a device"); | |||
841 | static unsigned int ide_nowerr; | 661 | static unsigned int ide_nowerr; |
842 | 662 | ||
843 | module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); | 663 | module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); |
844 | MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device"); | 664 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); |
845 | 665 | ||
846 | static unsigned int ide_cdroms; | 666 | static unsigned int ide_cdroms; |
847 | 667 | ||
@@ -906,7 +726,7 @@ static void ide_dev_apply_params(ide_drive_t *drive) | |||
906 | drive->noprobe = 1; | 726 | drive->noprobe = 1; |
907 | } | 727 | } |
908 | if (ide_nowerr & (1 << i)) { | 728 | if (ide_nowerr & (1 << i)) { |
909 | printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n", | 729 | printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n", |
910 | drive->name); | 730 | drive->name); |
911 | drive->bad_wstat = BAD_R_STAT; | 731 | drive->bad_wstat = BAD_R_STAT; |
912 | } | 732 | } |
@@ -927,7 +747,7 @@ static void ide_dev_apply_params(ide_drive_t *drive) | |||
927 | drive->cyl, drive->head, drive->sect); | 747 | drive->cyl, drive->head, drive->sect); |
928 | drive->present = 1; | 748 | drive->present = 1; |
929 | drive->media = ide_disk; | 749 | drive->media = ide_disk; |
930 | drive->ready_stat = READY_STAT; | 750 | drive->ready_stat = ATA_DRDY; |
931 | } | 751 | } |
932 | } | 752 | } |
933 | 753 | ||