bk://bart.bkbits.net/ide-dev-2.6 bzolnier@trik.(none)|ChangeSet|20050211194118|09537 bzolnier # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/02/28 01:15:44-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-ide-dev # # include/linux/ide.h # 2005/02/28 01:15:39-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/ide/ide-io.c # 2005/02/28 01:15:38-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/ide/ide-disk.c # 2005/02/28 01:15:38-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/02/20 12:52:57-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-ide-dev # # drivers/ide/ide.c # 2005/02/20 12:52:52-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/ide/ide-io.c # 2005/02/20 12:52:52-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/ide/Kconfig # 2005/02/20 12:52:52-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/02/11 23:00:23-08:00 akpm@bix.(none) # Merge bk://bart.bkbits.net/ide-dev-2.6 # into bix.(none):/usr/src/bk-ide-dev # # include/linux/ata.h # 2005/02/11 23:00:19-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/02/11 20:41:18+01:00 bzolnier@trik.(none) # [ide] fix io_32bit race in ide_taskfile_ioctl() # # In ide_taskfile_ioctl(), there was a race condition involving # drive->io_32bit. It was cleared and restored during ioctl # requests but there was no synchronization with other requests. # So, other requests could execute with the altered io_32bit # setting or updated drive->io_32bit could be overwritten by # ide_taskfile_ioctl(). # # This patch adds ATA_TFLAG_IO_16BIT flag to indicate to # ide_pio_datablock() that 16bit IO is needed regardless of # drive->io_32bit settting. # # Signed-off-by: Tejun Heo # # include/linux/ata.h # 2005/02/11 20:41:06+01:00 bzolnier@trik.(none) +1 -0 # [ide] fix io_32bit race in ide_taskfile_ioctl() # # drivers/ide/ide-taskfile.c # 2005/02/11 20:41:06+01:00 bzolnier@trik.(none) +12 -4 # [ide] fix io_32bit race in ide_taskfile_ioctl() # # ChangeSet # 2005/02/11 19:47:30+01:00 bzolnier@trik.(none) # [ide] fix unneeded LBA48 taskfile registers access # # This small patch fixes unneeded writes/reads to LBA48 taskfile registers # on LBA48 capable disks for following cases: # # * Power Management requests # (WIN_FLUSH_CACHE, WIN_STANDBYNOW1, WIN_IDLEIMMEDIATE commands) # * special commands (WIN_SPECIFY, WIN_RESTORE, WIN_SETMULT) # * Host Protected Area support (WIN_READ_NATIVE_MAX, WIN_SET_MAX) # * /proc/ide/ SMART support (WIN_SMART with SMART_ENABLE, # SMART_READ_VALUES and SMART_READ_THRESHOLDS subcommands) # * write cache enabling/disabling in ide-disk # (WIN_SETFEATURES with SETFEATURES_{EN,DIS}_WCACHE) # * write cache flushing in ide-disk (WIN_FLUSH_CACHE) # * acoustic management in ide-disk # (WIN_SETFEATURES with SETFEATURES_{EN,DIS}_AAM) # * door (un)locking in ide-disk (WIN_DOORLOCK, WIN_DOORUNLOCK) # * /proc/ide/hd?/identify support (WIN_IDENTIFY) # # Patch adds 'unsinged long flags' to ide_task_t and uses ATA_TFLAG_LBA48 # flag (from ) to indicate need of access to LBA48 taskfile # registers. # # include/linux/ide.h # 2005/02/11 19:47:18+01:00 bzolnier@trik.(none) +1 -0 # [ide] fix unneeded LBA48 taskfile registers access # # drivers/ide/ide-taskfile.c # 2005/02/11 19:47:18+01:00 bzolnier@trik.(none) +5 -2 # [ide] fix unneeded LBA48 taskfile registers access # # drivers/ide/ide-io.c # 2005/02/11 19:47:18+01:00 bzolnier@trik.(none) +4 -3 # [ide] fix unneeded LBA48 taskfile registers access # # drivers/ide/ide-disk.c # 2005/02/11 19:47:18+01:00 bzolnier@trik.(none) +9 -2 # [ide] fix unneeded LBA48 taskfile registers access # # ChangeSet # 2005/02/11 19:31:17+01:00 bzolnier@trik.(none) # [ide via82cxxx] add VIA VT6410 support # # From: Mathias Kretschmer # # include/linux/pci_ids.h # 2005/02/11 19:31:06+01:00 bzolnier@trik.(none) +1 -0 # [ide via82cxxx] add VIA VT6410 support # # drivers/ide/pci/via82cxxx.c # 2005/02/11 19:31:06+01:00 bzolnier@trik.(none) +21 -9 # [ide via82cxxx] add VIA VT6410 support # # ChangeSet # 2005/02/11 18:54:27+01:00 bzolnier@trik.(none) # [ide] fix OOPS in task_end_request() # # Requests generated by /proc/ide/hd?/identify # and /proc/ide/hd?/smart_{thresholds,values} # don't have valid rq->rq_disk set. # # Use ide_end_request() instead of ->end_request(). # # drivers/ide/ide-taskfile.c # 2005/02/11 18:54:16+01:00 bzolnier@trik.(none) +1 -4 # [ide] fix OOPS in task_end_request() # # ChangeSet # 2005/02/06 21:08:16+01:00 bzolnier@trik.(none) # [ide] fix ATAPI Power Management # # I've introduced bug in ATAPI Power Management handling, # idedisk_pm_idle shouldn't be done for ATAPI devices. # # drivers/ide/ide-io.c # 2005/02/05 01:44:33+01:00 bzolnier@trik.(none) +6 -0 # [ide] fix ATAPI Power Management # # ChangeSet # 2005/02/06 21:07:35+01:00 bzolnier@trik.(none) # [ide] fix pdc202xx_{new,old}.c after linux-2.6 merge # # drivers/ide/pci/pdc202xx_old.c # 2005/02/06 21:07:20+01:00 bzolnier@trik.(none) +0 -17 # [ide] fix pdc202xx_{new,old}.c after linux-2.6 merge # # drivers/ide/pci/pdc202xx_new.c # 2005/02/06 21:07:20+01:00 bzolnier@trik.(none) +0 -6 # [ide] fix pdc202xx_{new,old}.c after linux-2.6 merge # # ChangeSet # 2005/02/06 21:02:13+01:00 bzolnier@trik.(none) # Merge trik.(none):/home/bzolnier/bk/linux-2.6 # into trik.(none):/home/bzolnier/bk/ide-dev-2.6 # # BitKeeper/deleted/.del-pdc202xx_old.h~5487981ee32153be # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # BitKeeper/deleted/.del-pdc202xx_new.h~2890994593a7ec02 # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # include/linux/ide.h # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-probe.c # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # BitKeeper/deleted/.del-pdc202xx_old.h~5487981ee32153be # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Merge rename: drivers/ide/pci/pdc202xx_old.h -> BitKeeper/deleted/.del-pdc202xx_old.h~5487981ee32153be # # BitKeeper/deleted/.del-pdc202xx_new.h~2890994593a7ec02 # 2005/02/06 21:02:08+01:00 bzolnier@trik.(none) +0 -0 # Merge rename: drivers/ide/pci/pdc202xx_new.h -> BitKeeper/deleted/.del-pdc202xx_new.h~2890994593a7ec02 # # ChangeSet # 2005/02/04 00:40:24+01:00 bzolnier@trik.(none) # [ide] kill ide-default # # * add ide_drives list to list devices without a driver # * add __ide_add_setting() and use it for adding no auto remove entries # * kill ide-default pseudo-driver # # drivers/ide/ide.c # 2005/01/25 02:40:20+01:00 bzolnier@trik.(none) +31 -28 # [ide] kill ide-default # # drivers/ide/ide-proc.c # 2005/01/25 02:40:20+01:00 bzolnier@trik.(none) +5 -4 # [ide] kill ide-default # # drivers/ide/Makefile # 2005/01/25 02:40:20+01:00 bzolnier@trik.(none) +1 -2 # [ide] kill ide-default # # BitKeeper/deleted/.del-ide-default.c~ad4e75ad8a193ed5 # 2005/02/04 00:40:13+01:00 bzolnier@trik.(none) +0 -0 # [ide] kill ide-default # # ChangeSet # 2005/02/04 00:38:26+01:00 bzolnier@trik.(none) # [ide] get driver from rq->rq_disk->private_data # # * add ide_driver_t * to device drivers objects # * set it to point at driver's ide_driver_t # * store address of this entry in disk->private_data # * fix ide_{cd,disk,floppy,tape,scsi}_g accordingly # * use rq->rq_disk->private_data instead of drive->driver # to obtain driver (this allows us to kill ide-default) # # drivers/scsi/ide-scsi.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +13 -4 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +3 -1 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-taskfile.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +11 -3 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-tape.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +6 -2 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-io.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +36 -8 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-floppy.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +6 -2 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-dma.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +3 -1 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-disk.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +6 -2 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-cd.h # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +1 -0 # [ide] get driver from rq->rq_disk->private_data # # drivers/ide/ide-cd.c # 2005/01/25 02:40:10+01:00 bzolnier@trik.(none) +5 -2 # [ide] get driver from rq->rq_disk->private_data # # ChangeSet # 2005/02/04 00:35:41+01:00 bzolnier@trik.(none) # [ide] kill ide_drive_t->disk # # * move ->disk from ide_drive_t to driver specific objects # * make drivers allocate struct gendisk and setup rq->rq_disk # (there is no need to do this for REQ_DRIVE_TASKFILE requests) # * add ide_init_disk() helper and kill alloc_disks() in ide-probe.c # * kill no longer needed ide_open() and ide_fops[] in ide.c # # include/linux/ide.h # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +1 -2 # [ide] kill ide_drive_t->disk # # drivers/scsi/ide-scsi.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +18 -5 # [ide] kill ide_drive_t->disk # # drivers/ide/ide.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +0 -17 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-tape.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +25 -6 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-probe.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +13 -39 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-io.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +0 -2 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-floppy.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +30 -10 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-disk.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +17 -5 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-cd.h # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +1 -0 # [ide] kill ide_drive_t->disk # # drivers/ide/ide-cd.c # 2005/01/25 02:39:59+01:00 bzolnier@trik.(none) +38 -22 # [ide] kill ide_drive_t->disk # # ChangeSet # 2005/02/04 00:31:44+01:00 bzolnier@trik.(none) # [ide] add ide_{un}register_region() # # Add ide_{un}register_region() and fix ide-{tape,scsi}.c to register # block device number ranges. In ata_probe() only probe for modules. # # Behavior is unchanged because: # * if driver is already loaded and attached to drive ata_probe() # is not called et all # * if driver is loaded by ata_probe() it will register new number range # for a drive and this range will be found by kobj_lookup() # # If this is not clear please read http://lwn.net/Articles/25711/ # and see drivers/base/map.c. # # This patch makes it possible to move drive->disk allocation from # ide-probe.c to device drivers. # # include/linux/ide.h # 2005/01/25 02:39:47+01:00 bzolnier@trik.(none) +3 -0 # [ide] add ide_{un}register_region() # # drivers/scsi/ide-scsi.c # 2005/01/25 02:39:47+01:00 bzolnier@trik.(none) +4 -0 # [ide] add ide_{un}register_region() # # drivers/ide/ide-tape.c # 2005/01/25 02:39:47+01:00 bzolnier@trik.(none) +3 -0 # [ide] add ide_{un}register_region() # # drivers/ide/ide-probe.c # 2005/01/25 02:39:47+01:00 bzolnier@trik.(none) +44 -17 # [ide] add ide_{un}register_region() # # ChangeSet # 2005/02/04 00:30:10+01:00 bzolnier@trik.(none) # [ide] destroy_proc_ide_device() cleanup # # When this function is called device is already unbinded from a # driver so there are no driver /proc entries to remove. # # drivers/ide/ide-proc.c # 2005/01/25 02:39:35+01:00 bzolnier@trik.(none) +0 -3 # [ide] destroy_proc_ide_device() cleanup # # ChangeSet # 2005/02/04 00:29:13+01:00 bzolnier@trik.(none) # [ide] drive->dsc_overlap fix # # drive->dsc_overlap is supported only by ide-{cd,tape} drivers. # Add missing clearing of ->dsc_overlap to ide_{cd,tape}_release() # and move ->dsc_overlap setup from ide_register_subdriver() to # ide_cdrom_setup() (ide-tape enables it unconditionally). # # drivers/ide/ide.c # 2005/01/25 02:39:24+01:00 bzolnier@trik.(none) +0 -5 # [ide] drive->dsc_overlap fix # # drivers/ide/ide-tape.c # 2005/01/25 02:39:24+01:00 bzolnier@trik.(none) +1 -0 # [ide] drive->dsc_overlap fix # # drivers/ide/ide-cd.c # 2005/01/25 02:39:24+01:00 bzolnier@trik.(none) +4 -0 # [ide] drive->dsc_overlap fix # # ChangeSet # 2005/02/04 00:28:20+01:00 bzolnier@trik.(none) # [ide] drive->nice1 fix # # It is drive's property independent of the driver being used so move # drive->nice1 setup from ide_register_subdriver() to probe_hwif() in # ide-probe.c. As a result changing a driver which controls the drive # no longer affects this flag. # # drivers/ide/ide.c # 2005/01/25 02:39:13+01:00 bzolnier@trik.(none) +0 -1 # [ide] drive->nice1 fix # # drivers/ide/ide-probe.c # 2005/01/25 02:39:13+01:00 bzolnier@trik.(none) +8 -3 # [ide] drive->nice1 fix # # ChangeSet # 2005/02/04 00:27:16+01:00 bzolnier@trik.(none) # [ide] ide-tape: fix character device ->open() vs ->cleanup() race # # Similar to the same race but for the block device. # # * store pointer to struct ide_tape_obj in idetape_chrdevs[] # * rename idetape_chrdevs[] to idetape_devs[] and kill idetape_chrdev_t # * add ide_tape_chrdev_get() for getting reference to the tape # * store tape pointer in file->private_data and fix all users of it # * fix idetape_chrdev_{open,release}() to get/put reference to the tape # # drivers/ide/ide-tape.c # 2005/01/25 02:39:03+01:00 bzolnier@trik.(none) +51 -30 # [ide] ide-tape: fix character device ->open() vs ->cleanup() race # # ChangeSet # 2005/02/03 21:47:18+01:00 bzolnier@trik.(none) # [ide] fix via82cxxx resume failure # # With David Woodhouse . # # On resume from sleep, via_set_speed() doesn't reinstate the correct # mode, because it thinks the drive is already configured correctly. # # Also kill redundant printk, ide_config_drive_speed() warns about errors. # # drivers/ide/pci/via82cxxx.c # 2005/02/03 21:47:05+01:00 bzolnier@trik.(none) +2 -5 # [ide] fix via82cxxx resume failure # # ChangeSet # 2005/02/03 21:20:52+01:00 bzolnier@trik.(none) # [ide] ide-scsi: add basic refcounting # # * pointers to a SCSI host and a drive are added to idescsi_scsi_t # * pointer to the SCSI host is stored in disk->private_data # * ide_scsi_{get,put}() is used to {get,put} reference to the SCSI host # # drivers/scsi/ide-scsi.c # 2005/01/21 23:41:42+01:00 bzolnier@trik.(none) +58 -11 # [ide] ide-scsi: add basic refcounting # # ChangeSet # 2005/02/03 21:19:36+01:00 bzolnier@trik.(none) # [ide] ide-tape: add basic refcounting # # Similar changes as for ide-cd.c. # # drivers/ide/ide-tape.c # 2005/01/21 23:41:25+01:00 bzolnier@trik.(none) +80 -14 # [ide] ide-tape: add basic refcounting # # ChangeSet # 2005/02/03 21:18:37+01:00 bzolnier@trik.(none) # [ide] ide-floppy: add basic refcounting # # Similar changes as for ide-cd.c. # # drivers/ide/ide-floppy.c # 2005/01/21 23:41:14+01:00 bzolnier@trik.(none) +90 -25 # [ide] ide-floppy: add basic refcounting # # ChangeSet # 2005/02/03 21:17:26+01:00 bzolnier@trik.(none) # [ide] ide-disk: add basic refcounting # # Similar changes as for ide-cd.c (except that struct ide_disk_obj is added). # # drivers/ide/ide-disk.c # 2005/01/21 23:41:03+01:00 bzolnier@trik.(none) +88 -9 # [ide] ide-disk: add basic refcounting # # ChangeSet # 2005/02/03 21:15:21+01:00 bzolnier@trik.(none) # [ide] ide-cd: add basic refcounting # # * based on reference counting in drivers/scsi/{sd,sr}.c # * fixes race between ->open() and ->cleanup() (ide_unregister_subdriver() # tests for drive->usage != 0 but there is no protection against new users) # * struct kref and pointer to a drive are added to struct ide_cdrom_info # * pointer to drive's struct ide_cdrom_info is stored in disk->private_data # * ide_cd_{get,put}() is used to {get,put} reference to struct ide_cdrom_info # * ide_cd_release() is a release method for struct ide_cdrom_info # # drivers/ide/ide-cd.h # 2005/01/21 23:40:52+01:00 bzolnier@trik.(none) +2 -0 # [ide] ide-cd: add basic refcounting # # drivers/ide/ide-cd.c # 2005/01/21 23:40:52+01:00 bzolnier@trik.(none) +80 -19 # [ide] ide-cd: add basic refcounting # # ChangeSet # 2005/02/03 21:13:29+01:00 bzolnier@trik.(none) # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # As a result disk->private_data can be used by device drivers now. # # include/linux/ide.h # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/scsi/ide-scsi.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +2 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -2 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-tape.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-floppy.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-disk.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +2 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-cd.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # ChangeSet # 2005/02/03 21:08:15+01:00 bzolnier@trik.(none) # [ide] kill setup_driver_defaults() # # * move default_do_request() to ide-default.c # * fix drivers to set ide_driver_t->{do_request,end_request,error,abort} # * kill setup_driver_defaults() # # drivers/ide/ide.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +0 -37 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-tape.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-io.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +4 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-floppy.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-disk.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +3 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-default.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +10 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-cd.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +3 -0 # [ide] kill setup_driver_defaults() # # ChangeSet # 2005/02/03 21:04:06+01:00 bzolnier@trik.(none) # [ide] kill ide_driver_t->capacity # # * add private /proc/ide/hd?/capacity handlers to ide-{cd,disk,floppy}.c # * use generic proc_ide_read_capacity() for ide-{scsi,tape}.c # * kill ->capacity, default_capacity() and generic_subdriver_entries[] # # include/linux/ide.h # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +0 -1 # [ide] kill ide_driver_t->capacity # # drivers/scsi/ide-scsi.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +10 -0 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide.c # 2005/02/03 21:00:44+01:00 bzolnier@trik.(none) +1 -15 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-tape.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +1 -0 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-proc.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +3 -5 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-floppy.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +11 -1 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-disk.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +11 -1 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-cd.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +20 -1 # [ide] kill ide_driver_t->capacity # # ChangeSet # 2005/02/03 20:44:44+01:00 bzolnier@trik.(none) # Merge # # include/linux/ide.h # 2005/02/03 20:44:41+01:00 bzolnier@trik.(none) +0 -0 # SCCS merged # # drivers/ide/ide-iops.c # 2005/02/03 20:44:41+01:00 bzolnier@trik.(none) +0 -0 # SCCS merged # # drivers/scsi/ide-scsi.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-taskfile.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-tape.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-probe.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-io.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-floppy.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-disk.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/21 20:25:56+01:00 bzolnier@trik.(none) # [ide] kill ide_driver_t->pre_reset # # Add ide_drive_t->post_reset flag and use it to signal post reset # condition to the ide-tape driver (the only user of ->pre_reset). # # include/linux/ide.h # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +1 -1 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +0 -5 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide-tape.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +5 -11 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide-iops.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +1 -1 # [ide] kill ide_driver_t->pre_reset # # ChangeSet # 2005/01/21 20:24:38+01:00 bzolnier@trik.(none) # [ide] fix some rare ide-default vs ide-disk races # # Some rare races between ide-default and ide-disk are possible, i.e.: # * ide-default is used, I/O request is triggered (ie. /proc/ide/hd?/identify), # drive->special is cleared silently (so CHS is not initialized properly), # ide-disk is loaded and fails if drive uses CHS # * ide-disk is used, drive is resetted, ide-disk is unloaded, ide-default # takes control over drive and on the first I/O request silently clears # drive->special without restoring settings # # Fix them by moving idedisk_{special,pre_reset}() and company to IDE core. # # include/linux/ide.h # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -10 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-taskfile.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -6 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-probe.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +58 -2 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-iops.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +19 -1 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-io.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +66 -2 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-disk.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -108 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/Kconfig # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix some rare ide-default vs ide-disk races # # ChangeSet # 2005/01/21 20:23:26+01:00 bzolnier@trik.(none) # [ide] generic Power Management for IDE devices # # Move PM code from ide-cd.c and ide-disk.c to IDE core so: # * PM is supported for other ATAPI devices (floppy, tape) # * PM is supported even if specific driver is not loaded # # include/linux/ide.h # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -2 # [ide] generic Power Management for IDE devices # # drivers/ide/ide.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -9 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-io.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +89 -2 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-disk.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -86 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-cd.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -41 # [ide] generic Power Management for IDE devices # # ChangeSet # 2005/01/21 20:21:54+01:00 bzolnier@trik.(none) # [ide] fix drive->ready_stat for ATAPI # # ATAPI devices ignore DRDY bit so drive->ready_stat must be set to zero. # It is currently done by device drivers (including ide-default fake driver) # but for PMAC driver it is too late as wait_for_ready() may be called during # probe: probe_hwif()->pmac_ide_dma_check()->pmac_ide_{mdma,udma}_enable()-> # ->pmac_ide_do_setfeature()->wait_for_ready(). # # Fixup drive->ready_stat just after detecting ATAPI device. # # drivers/scsi/ide-scsi.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-tape.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -2 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-probe.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-floppy.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-default.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -7 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-cd.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # ChangeSet # 2005/01/21 20:20:25+01:00 bzolnier@trik.(none) # [ide] ignore BIOS enable bits for Promise controllers # # Since there are no Promise binary drivers for 2.6.x kernels: # * ignore BIOS enable bits completely # * remove CONFIG_PDC202XX_FORCE # * kill IDEPCI_FLAG_FORCE_PDC hack # # include/linux/ide.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -1 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/setup-pci.c # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +1 -14 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/pci/pdc202xx_old.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -17 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/pci/pdc202xx_new.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -6 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/Kconfig # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -7 # [ide] ignore BIOS enable bits for Promise controllers # diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/Kconfig 2005-02-28 17:22:05 -08:00 @@ -150,7 +150,6 @@ config IDEDISK_MULTI_MODE bool "Use multi-mode by default" - depends on BLK_DEV_IDEDISK help If you get this error, try to say Y here: @@ -658,13 +657,6 @@ config BLK_DEV_PDC202XX_NEW tristate "PROMISE PDC202{68|69|70|71|75|76|77} support" - -# FIXME - probably wants to be one for old and for new -config PDC202XX_FORCE - bool "Enable controller even if disabled by BIOS" - depends on BLK_DEV_PDC202XX_NEW - help - Enable the PDC202xx controller even if it has been disabled in the BIOS setup. config BLK_DEV_SVWKS tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support" diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/Makefile 2005-02-28 17:22:05 -08:00 @@ -13,8 +13,7 @@ obj-$(CONFIG_BLK_DEV_IDE) += pci/ -ide-core-y += ide.o ide-default.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o +ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-cd.c 2005-02-28 17:22:05 -08:00 @@ -324,6 +324,34 @@ #include "ide-cd.h" +static DECLARE_MUTEX(idecd_ref_sem); + +#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) + +#define ide_cd_g(disk) \ + container_of((disk)->private_data, struct cdrom_info, driver) + +static struct cdrom_info *ide_cd_get(struct gendisk *disk) +{ + struct cdrom_info *cd = NULL; + + down(&idecd_ref_sem); + cd = ide_cd_g(disk); + if (cd) + kref_get(&cd->kref); + up(&idecd_ref_sem); + return cd; +} + +static void ide_cd_release(struct kref *); + +static void ide_cd_put(struct cdrom_info *cd) +{ + down(&idecd_ref_sem); + kref_put(&cd->kref, ide_cd_release); + up(&idecd_ref_sem); +} + /**************************************************************************** * Generic packet command support and error handling routines. */ @@ -529,10 +557,13 @@ /* * Initialize a ide-cd packet command request */ -static void cdrom_prepare_request(struct request *rq) +static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq) { + struct cdrom_info *cd = drive->driver_data; + ide_init_drive_cmd(rq); rq->flags = REQ_PC; + rq->rq_disk = cd->disk; } static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, @@ -545,7 +576,7 @@ sense = &info->sense_data; /* stuff the sense request in front of our current request */ - cdrom_prepare_request(rq); + cdrom_prepare_request(drive, rq); rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; @@ -1829,7 +1860,7 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) { struct cdrom_info *info = drive->driver_data; - struct gendisk *g = drive->disk; + struct gendisk *g = info->disk; unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; /* @@ -2021,7 +2052,7 @@ struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_TEST_UNIT_READY; @@ -2053,7 +2084,7 @@ if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { stat = 0; } else { - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; req.cmd[4] = lockflag ? 1 : 0; @@ -2097,7 +2128,7 @@ if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) return 0; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); /* only tell drive to close tray if open, if it can do that */ if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray) @@ -2121,7 +2152,7 @@ int stat; struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; @@ -2144,7 +2175,7 @@ { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.data = buf; @@ -2201,7 +2232,7 @@ if (stat) toc->capacity = 0x1fffff; - set_capacity(drive->disk, toc->capacity * sectors_per_frame); + set_capacity(info->disk, toc->capacity * sectors_per_frame); blk_queue_hardsect_size(drive->queue, sectors_per_frame << SECTOR_BITS); @@ -2321,7 +2352,7 @@ stat = cdrom_get_last_written(cdi, &last_written); if (!stat && (last_written > toc->capacity)) { toc->capacity = last_written; - set_capacity(drive->disk, toc->capacity * sectors_per_frame); + set_capacity(info->disk, toc->capacity * sectors_per_frame); } /* Remember that we've read this stuff. */ @@ -2336,7 +2367,7 @@ { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.data = buf; @@ -2356,7 +2387,7 @@ struct request_sense *sense) { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; if (speed == 0) @@ -2386,7 +2417,7 @@ struct request_sense sense; struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = &sense; req.cmd[0] = GPCMD_PLAY_AUDIO_MSF; @@ -2436,7 +2467,7 @@ /* here we queue the commands from the uniform CD-ROM layer. the packet must be complete, as we do not touch it at all. */ - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE); if (cgc->sense) memset(cgc->sense, 0, sizeof(struct request_sense)); @@ -2586,7 +2617,7 @@ struct request req; int ret; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.flags = REQ_SPECIAL | REQ_QUIET; ret = ide_do_drive_cmd(drive, &req, ide_wait); @@ -2830,7 +2861,7 @@ if (!CDROM_CONFIG_FLAGS(drive)->mo_drive) devinfo->mask |= CDC_MO_DRIVE; - devinfo->disk = drive->disk; + devinfo->disk = info->disk; return register_cdrom(devinfo); } @@ -3088,7 +3119,6 @@ drive->queue->unplug_delay = 1; drive->special.all = 0; - drive->ready_stat = 0; CDROM_STATE_FLAGS(drive)->media_changed = 1; CDROM_STATE_FLAGS(drive)->toc_valid = 0; @@ -3193,6 +3223,9 @@ */ blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE); + if (drive->autotune == IDE_TUNE_DEFAULT || + drive->autotune == IDE_TUNE_AUTO) + drive->dsc_overlap = (drive->next != drive); #if 0 drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1; if (HWIF(drive)->no_dsc) { @@ -3226,14 +3259,27 @@ int ide_cdrom_cleanup(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - struct gendisk *g = drive->disk; if (ide_unregister_subdriver(drive)) { printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n", __FUNCTION__, drive->name); return 1; } + + del_gendisk(info->disk); + + ide_cd_put(info); + + return 0; +} + +static void ide_cd_release(struct kref *kref) +{ + struct cdrom_info *info = to_ide_cd(kref); + struct cdrom_device_info *devinfo = &info->devinfo; + ide_drive_t *drive = info->drive; + struct gendisk *g = info->disk; + if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) @@ -3241,56 +3287,37 @@ if (info->changer_info != NULL) kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk(KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); + printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " + "driver.\n", __FUNCTION__, drive->name); + drive->dsc_overlap = 0; drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); - del_gendisk(g); - g->fops = ide_fops; - return 0; + g->private_data = NULL; + put_disk(g); + kfree(info); } static int ide_cdrom_attach (ide_drive_t *drive); -/* - * Power Management state machine. - * - * We don't do much for CDs right now. - */ - -static void ide_cdrom_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error) +#ifdef CONFIG_PROC_FS +static int proc_idecd_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) { -} - -static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, struct request *rq) -{ - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (rq->pm->pm_step) { - case ide_pm_state_start_suspend: - break; + ide_drive_t*drive = (ide_drive_t *)data; + int len; - case ide_pm_state_start_resume: /* Resume step 1 (restore DMA) */ - /* - * Right now, all we do is call hwif->ide_dma_check(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - * Also, this step could be implemented as a generic helper - * as most subdrivers will use it. - */ - if ((drive->id->capability & 1) == 0) - break; - if (HWIF(drive)->ide_dma_check == NULL) - break; - HWIF(drive)->ide_dma_check(drive); - break; - } - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; + len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static ide_proc_entry_t idecd_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#else +# define idecd_proc NULL +#endif + static ide_driver_t ide_cdrom_driver = { .owner = THIS_MODULE, .name = "ide-cdrom", @@ -3300,18 +3327,26 @@ .supports_dsc_overlap = 1, .cleanup = ide_cdrom_cleanup, .do_request = ide_do_rw_cdrom, - .capacity = ide_cdrom_capacity, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, + .proc = idecd_proc, .attach = ide_cdrom_attach, .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), - .start_power_step = ide_cdrom_start_power_step, - .complete_power_step = ide_cdrom_complete_power_step, }; static int idecd_open(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info; + ide_drive_t *drive; int rc = -ENOMEM; + + if (!(info = ide_cd_get(disk))) + return -ENXIO; + + drive = info->drive; + drive->usage++; if (!info->buffer) @@ -3319,16 +3354,24 @@ GFP_KERNEL|__GFP_REPEAT); if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file))) drive->usage--; + + if (rc < 0) + ide_cd_put(info); + return rc; } static int idecd_release(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info = ide_cd_g(disk); + ide_drive_t *drive = info->drive; cdrom_release (&info->devinfo, file); drive->usage--; + + ide_cd_put(info); + return 0; } @@ -3336,27 +3379,27 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - int err = generic_ide_ioctl(file, bdev, cmd, arg); - if (err == -EINVAL) { - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = ide_cd_g(bdev->bd_disk); + int err; + + err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); + if (err == -EINVAL) err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); - } + return err; } static int idecd_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = ide_cd_g(disk); return cdrom_media_changed(&info->devinfo); } static int idecd_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; + struct cdrom_info *info = ide_cd_g(disk); struct request_sense sense; - cdrom_read_toc(drive, &sense); + cdrom_read_toc(info->drive, &sense); return 0; } @@ -3378,7 +3421,7 @@ static int ide_cdrom_attach (ide_drive_t *drive) { struct cdrom_info *info; - struct gendisk *g = drive->disk; + struct gendisk *g; struct request_sense sense; if (!strstr("ide-cdrom", drive->driver_req)) @@ -3403,14 +3446,30 @@ printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); goto failed; } + + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_free_cd; + + ide_init_disk(g, drive); + if (ide_register_subdriver(drive, &ide_cdrom_driver)) { printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name); - kfree(info); - goto failed; + goto out_put_disk; } memset(info, 0, sizeof (struct cdrom_info)); + + kref_init(&info->kref); + + info->drive = drive; + info->driver = &ide_cdrom_driver; + info->disk = g; + + g->private_data = &info->driver; + drive->driver_data = info; + DRIVER(drive)->busy++; g->minors = 1; snprintf(g->devfs_name, sizeof(g->devfs_name), @@ -3440,6 +3499,11 @@ g->flags |= GENHD_FL_REMOVABLE; add_disk(g); return 0; + +out_put_disk: + put_disk(g); +out_free_cd: + kfree(info); failed: return 1; } diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h --- a/drivers/ide/ide-cd.h 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-cd.h 2005-02-28 17:22:05 -08:00 @@ -460,6 +460,10 @@ /* Extra per-device info for cdrom drives. */ struct cdrom_info { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct kref kref; /* Buffer for table of contents. NULL if we haven't allocated a TOC buffer for this device yet. */ diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c --- a/drivers/ide/ide-default.c 2005-02-28 17:22:05 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,73 +0,0 @@ -/* - * ide-default - Driver for unbound ide devices - * - * This provides a clean way to bind a device to default operations - * by having an actual driver class that rather than special casing - * "no driver" all over the IDE code - * - * Copyright (C) 2003, Red Hat - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define IDEDEFAULT_VERSION "0.9.newide" -/* - * Driver initialization. - */ - -static int idedefault_attach(ide_drive_t *drive); - -/* - * IDE subdriver functions, registered with ide.c - */ - -ide_driver_t idedefault_driver = { - .name = "ide-default", - .version = IDEDEFAULT_VERSION, - .attach = idedefault_attach, - .cleanup = ide_unregister_subdriver, - .drives = LIST_HEAD_INIT(idedefault_driver.drives) -}; - -static int idedefault_attach (ide_drive_t *drive) -{ - if (ide_register_subdriver(drive, &idedefault_driver)) { - printk(KERN_ERR "ide-default: %s: Failed to register the " - "driver with ide.c\n", drive->name); - return 1; - } - - /* For the sake of the request layer, we must make sure we have a - * correct ready_stat value, that is 0 for ATAPI devices or we will - * fail any request like Power Management - */ - if (drive->media != ide_disk) - drive->ready_stat = 0; - - return 0; -} - -MODULE_DESCRIPTION("IDE Default Driver"); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-disk.c 2005-02-28 17:22:05 -08:00 @@ -71,6 +71,41 @@ #include #include +struct ide_disk_obj { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct kref kref; +}; + +static DECLARE_MUTEX(idedisk_ref_sem); + +#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) + +#define ide_disk_g(disk) \ + container_of((disk)->private_data, struct ide_disk_obj, driver) + +static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) +{ + struct ide_disk_obj *idkp = NULL; + + down(&idedisk_ref_sem); + idkp = ide_disk_g(disk); + if (idkp) + kref_get(&idkp->kref); + up(&idedisk_ref_sem); + return idkp; +} + +static void ide_disk_release(struct kref *); + +static void ide_disk_put(struct ide_disk_obj *idkp) +{ + down(&idedisk_ref_sem); + kref_put(&idkp->kref, ide_disk_release); + up(&idedisk_ref_sem); +} + /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" * value for this drive (from its reported identification information). @@ -325,6 +360,9 @@ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; args.command_type = IDE_DRIVE_TASK_NO_DATA; args.handler = &task_no_data_intr; + + args.flags |= ATA_TFLAG_LBA48; + /* submit command request */ ide_raw_taskfile(drive, &args, NULL); @@ -394,6 +432,9 @@ args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); args.command_type = IDE_DRIVE_TASK_NO_DATA; args.handler = &task_no_data_intr; + + args.flags |= ATA_TFLAG_LBA48; + /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ @@ -514,75 +555,6 @@ return drive->capacity64 - drive->sect0; } -#define IS_PDC4030_DRIVE 0 - -static ide_startstop_t idedisk_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - if (s->b.set_geometry) { - s->b.set_geometry = 0; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl; - args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; - args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &set_geometry_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->b.recalibrate) { - s->b.recalibrate = 0; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &recal_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->b.set_multmode) { - s->b.set_multmode = 0; - if (drive->mult_req > drive->id->max_multsect) - drive->mult_req = drive->id->max_multsect; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &set_multmode_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->all) { - int special = s->all; - s->all = 0; - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); - return ide_stopped; - } - return IS_PDC4030_DRIVE ? ide_stopped : ide_started; -} - -static void idedisk_pre_reset (ide_drive_t *drive) -{ - int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - if (OK_TO_RESET_CONTROLLER) - drive->mult_count = 0; - if (!drive->keep_settings && !drive->using_dma) - drive->mult_req = 0; - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - #ifdef CONFIG_PROC_FS static int smart_enable(ide_drive_t *drive) @@ -646,6 +618,16 @@ PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static int proc_idedisk_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_drive_t*drive = (ide_drive_t *)data; + int len; + + len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} + static int proc_idedisk_read_smart_thresholds (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -686,6 +668,7 @@ static ide_proc_entry_t idedisk_proc[] = { { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, + { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, @@ -790,9 +773,10 @@ ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); - if (ide_id_has_flush_cache_ext(drive->id)) + if (ide_id_has_flush_cache_ext(drive->id)) { args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; - else + args.flags |= ATA_TFLAG_LBA48; + } else args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; args.command_type = IDE_DRIVE_TASK_NO_DATA; args.handler = &task_no_data_intr; @@ -852,90 +836,6 @@ ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } -/* - * Power Management state machine. This one is rather trivial for now, - * we should probably add more, like switching back to PIO on suspend - * to help some BIOSes, re-do the door locking on resume, etc... - */ - -enum { - idedisk_pm_flush_cache = ide_pm_state_start_suspend, - idedisk_pm_standby, - - idedisk_pm_idle = ide_pm_state_start_resume, - idedisk_pm_restore_dma, -}; - -static void idedisk_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error) -{ - switch (rq->pm->pm_step) { - case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ - if (rq->pm->pm_state == 4) - rq->pm->pm_step = ide_pm_state_completed; - else - rq->pm->pm_step = idedisk_pm_standby; - break; - case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ - rq->pm->pm_step = ide_pm_state_completed; - break; - case idedisk_pm_idle: /* Resume step 1 (idle) complete */ - rq->pm->pm_step = idedisk_pm_restore_dma; - break; - } -} - -static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, struct request *rq) -{ - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (rq->pm->pm_step) { - case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) */ - /* Not supported? Switch to next step now. */ - if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { - idedisk_complete_power_step(drive, rq, 0, 0); - return ide_stopped; - } - if (ide_id_has_flush_cache_ext(drive->id)) - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; - else - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_standby: /* Suspend step 2 (standby) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_idle: /* Resume step 1 (idle) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_restore_dma: /* Resume step 2 (restore DMA) */ - /* - * Right now, all we do is call hwif->ide_dma_check(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - * Also, this step could be implemented as a generic helper - * as most subdrivers will use it - */ - if ((drive->id->capability & 1) == 0) - break; - if (HWIF(drive)->ide_dma_check == NULL) - break; - HWIF(drive)->ide_dma_check(drive); - break; - } - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; -} - static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -974,28 +874,6 @@ printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2); - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; - } - - /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; - } - - /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; - } - /* calculate drive capacity, and select LBA if possible */ init_idedisk_capacity (drive); @@ -1059,21 +937,6 @@ ide_dma_verbose(drive); printk("\n"); - drive->mult_count = 0; - if (id->max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE - id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; - id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; - drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; -#endif /* CONFIG_IDEDISK_MULTI_MODE */ - } drive->no_io_32bit = id->dword_io ? 1 : 0; /* write cache enabled? */ @@ -1117,16 +980,32 @@ static int idedisk_cleanup (ide_drive_t *drive) { - struct gendisk *g = drive->disk; + struct ide_disk_obj *idkp = drive->driver_data; + struct gendisk *g = idkp->disk; + ide_cacheflush_p(drive); if (ide_unregister_subdriver(drive)) return 1; del_gendisk(g); - drive->devfs_name[0] = '\0'; - g->fops = ide_fops; + + ide_disk_put(idkp); + return 0; } +static void ide_disk_release(struct kref *kref) +{ + struct ide_disk_obj *idkp = to_ide_disk(kref); + ide_drive_t *drive = idkp->drive; + struct gendisk *g = idkp->disk; + + drive->driver_data = NULL; + drive->devfs_name[0] = '\0'; + g->private_data = NULL; + put_disk(g); + kfree(idkp); +} + static int idedisk_attach(ide_drive_t *drive); static void ide_device_shutdown(struct device *dev) @@ -1172,19 +1051,25 @@ .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, .do_request = ide_do_rw_disk, - .pre_reset = idedisk_pre_reset, - .capacity = idedisk_capacity, - .special = idedisk_special, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, .proc = idedisk_proc, .attach = idedisk_attach, .drives = LIST_HEAD_INIT(idedisk_driver.drives), - .start_power_step = idedisk_start_power_step, - .complete_power_step = idedisk_complete_power_step, }; static int idedisk_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_disk_obj *idkp; + ide_drive_t *drive; + + if (!(idkp = ide_disk_get(disk))) + return -ENXIO; + + drive = idkp->drive; + drive->usage++; if (drive->removable && drive->usage == 1) { ide_task_t args; @@ -1206,7 +1091,10 @@ static int idedisk_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_disk_obj *idkp = ide_disk_g(disk); + ide_drive_t *drive = idkp->drive; + if (drive->usage == 1) ide_cacheflush_p(drive); if (drive->removable && drive->usage == 1) { @@ -1219,6 +1107,9 @@ drive->doorlocking = 0; } drive->usage--; + + ide_disk_put(idkp); + return 0; } @@ -1226,12 +1117,14 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - return generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); + return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); } static int idedisk_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; + struct ide_disk_obj *idkp = ide_disk_g(disk); + ide_drive_t *drive = idkp->drive; /* do not scan partitions twice if this is a removable device */ if (drive->attach) { @@ -1244,8 +1137,8 @@ static int idedisk_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - set_capacity(disk, idedisk_capacity(drive)); + struct ide_disk_obj *idkp = ide_disk_g(disk); + set_capacity(disk, idedisk_capacity(idkp->drive)); return 0; } @@ -1262,7 +1155,8 @@ static int idedisk_attach(ide_drive_t *drive) { - struct gendisk *g = drive->disk; + struct ide_disk_obj *idkp; + struct gendisk *g; /* strstr("foo", "") is non-NULL */ if (!strstr("ide-disk", drive->driver_req)) @@ -1272,10 +1166,33 @@ if (drive->media != ide_disk) goto failed; + idkp = kmalloc(sizeof(*idkp), GFP_KERNEL); + if (!idkp) + goto failed; + + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_free_idkp; + + ide_init_disk(g, drive); + if (ide_register_subdriver(drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - goto failed; + goto out_put_disk; } + + memset(idkp, 0, sizeof(*idkp)); + + kref_init(&idkp->kref); + + idkp->drive = drive; + idkp->driver = &idedisk_driver; + idkp->disk = g; + + g->private_data = &idkp->driver; + + drive->driver_data = idkp; + DRIVER(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { @@ -1293,6 +1210,11 @@ g->fops = &idedisk_ops; add_disk(g); return 0; + +out_put_disk: + put_disk(g); +out_free_idkp: + kfree(idkp); failed: return 1; } diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-dma.c 2005-02-28 17:22:05 -08:00 @@ -175,8 +175,10 @@ if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (!dma_stat) { struct request *rq = HWGROUP(drive)->rq; + ide_driver_t *drv; - DRIVER(drive)->end_request(drive, 1, rq->nr_sectors); + drv = *(ide_driver_t **)rq->rq_disk->private_data;; + drv->end_request(drive, 1, rq->nr_sectors); return ide_stopped; } printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-floppy.c 2005-02-28 17:22:05 -08:00 @@ -274,8 +274,11 @@ * driver due to an interrupt or a timer event is stored in a variable * of type idefloppy_floppy_t, defined below. */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_floppy_obj { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct kref kref; /* Current packet command */ idefloppy_pc_t *pc; @@ -514,6 +517,34 @@ u8 reserved[4]; } idefloppy_mode_parameter_header_t; +static DECLARE_MUTEX(idefloppy_ref_sem); + +#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) + +#define ide_floppy_g(disk) \ + container_of((disk)->private_data, struct ide_floppy_obj, driver) + +static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) +{ + struct ide_floppy_obj *floppy = NULL; + + down(&idefloppy_ref_sem); + floppy = ide_floppy_g(disk); + if (floppy) + kref_get(&floppy->kref); + up(&idefloppy_ref_sem); + return floppy; +} + +static void ide_floppy_release(struct kref *); + +static void ide_floppy_put(struct ide_floppy_obj *floppy) +{ + down(&idefloppy_ref_sem); + kref_put(&floppy->kref, ide_floppy_release); + up(&idefloppy_ref_sem); +} + /* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. @@ -652,9 +683,12 @@ */ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq) { + struct ide_floppy_obj *floppy = drive->driver_data; + ide_init_drive_cmd(rq); rq->buffer = (char *) pc; rq->flags = REQ_SPECIAL; //rq->cmd = IDEFLOPPY_PC_RQ; + rq->rq_disk = floppy->disk; (void) ide_do_drive_cmd(drive, rq, ide_preempt); } @@ -1246,7 +1280,8 @@ unsigned long block = (unsigned long)block_s; debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", - rq->rq_status, rq->rq_disk->disk_name, + rq->rq_status, + rq->rq_disk ? rq->rq_disk->disk_name ? "?", rq->flags, rq->errors); debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " "current_nr_sectors: %d\n", (long)rq->sector, @@ -1301,11 +1336,13 @@ */ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc) { + struct ide_floppy_obj *floppy = drive->driver_data; struct request rq; ide_init_drive_cmd (&rq); rq.buffer = (char *) pc; rq.flags = REQ_SPECIAL; // rq.cmd = IDEFLOPPY_PC_RQ; + rq.rq_disk = floppy->disk; return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -1330,7 +1367,7 @@ } header = (idefloppy_mode_parameter_header_t *) pc.buffer; floppy->wp = header->wp; - set_disk_ro(drive->disk, floppy->wp); + set_disk_ro(floppy->disk, floppy->wp); page = (idefloppy_flexible_disk_page_t *) (header + 1); page->transfer_rate = ntohs(page->transfer_rate); @@ -1396,7 +1433,7 @@ drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = floppy->bs_factor = 0; - set_capacity(drive->disk, 0); + set_capacity(floppy->disk, 0); idefloppy_create_read_capacity_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { @@ -1470,7 +1507,7 @@ (void) idefloppy_get_flexible_disk_page(drive); } - set_capacity(drive->disk, floppy->blocks * floppy->bs_factor); + set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor); return rc; } @@ -1792,10 +1829,6 @@ struct idefloppy_id_gcw gcw; *((u16 *) &gcw) = drive->id->config; - drive->driver_data = floppy; - drive->ready_stat = 0; - memset(floppy, 0, sizeof(idefloppy_floppy_t)); - floppy->drive = drive; floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); @@ -1835,20 +1868,44 @@ static int idefloppy_cleanup (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - struct gendisk *g = drive->disk; + struct gendisk *g = floppy->disk; if (ide_unregister_subdriver(drive)) return 1; - drive->driver_data = NULL; - kfree(floppy); + del_gendisk(g); - g->fops = ide_fops; + + ide_floppy_put(floppy); + return 0; } +static void ide_floppy_release(struct kref *kref) +{ + struct ide_floppy_obj *floppy = to_ide_floppy(kref); + ide_drive_t *drive = floppy->drive; + struct gendisk *g = floppy->disk; + + drive->driver_data = NULL; + g->private_data = NULL; + put_disk(g); + kfree(floppy); +} + #ifdef CONFIG_PROC_FS +static int proc_idefloppy_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_drive_t*drive = (ide_drive_t *)data; + int len; + + len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} + static ide_proc_entry_t idefloppy_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; @@ -1874,7 +1931,8 @@ .cleanup = idefloppy_cleanup, .do_request = idefloppy_do_request, .end_request = idefloppy_do_end_request, - .capacity = idefloppy_capacity, + .error = __ide_error, + .abort = __ide_abort, .proc = idefloppy_proc, .attach = idefloppy_attach, .drives = LIST_HEAD_INIT(idefloppy_driver.drives), @@ -1882,14 +1940,21 @@ static int idefloppy_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_floppy_obj *floppy; + ide_drive_t *drive; idefloppy_pc_t pc; + int ret = 0; - drive->usage++; - debug_log(KERN_INFO "Reached idefloppy_open\n"); + if (!(floppy = ide_floppy_get(disk))) + return -ENXIO; + + drive = floppy->drive; + + drive->usage++; + if (drive->usage == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); /* Just in case */ @@ -1909,13 +1974,15 @@ */ ) { drive->usage--; - return -EIO; + ret = -EIO; + goto out_put_floppy; } if (floppy->wp && (filp->f_mode & 2)) { drive->usage--; - return -EROFS; - } + ret = -EROFS; + goto out_put_floppy; + } set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { @@ -1925,21 +1992,26 @@ check_disk_change(inode->i_bdev); } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { drive->usage--; - return -EBUSY; + ret = -EBUSY; + goto out_put_floppy; } return 0; + +out_put_floppy: + ide_floppy_put(floppy); + return ret; } static int idefloppy_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + ide_drive_t *drive = floppy->drive; idefloppy_pc_t pc; debug_log(KERN_INFO "Reached idefloppy_release\n"); if (drive->usage == 1) { - idefloppy_floppy_t *floppy = drive->driver_data; - /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd(&pc, 0); @@ -1949,6 +2021,9 @@ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); } drive->usage--; + + ide_floppy_put(floppy); + return 0; } @@ -1956,10 +2031,10 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); + ide_drive_t *drive = floppy->drive; void __user *argp = (void __user *)arg; - int err = generic_ide_ioctl(file, bdev, cmd, arg); + int err = generic_ide_ioctl(drive, file, bdev, cmd, arg); int prevent = (arg) ? 1 : 0; idefloppy_pc_t pc; if (err != -EINVAL) @@ -2020,8 +2095,8 @@ static int idefloppy_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + ide_drive_t *drive = floppy->drive; /* do not scan partitions twice if this is a removable device */ if (drive->attach) { @@ -2033,8 +2108,8 @@ static int idefloppy_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - set_capacity(disk, idefloppy_capacity(drive)); + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + set_capacity(disk, idefloppy_capacity(floppy->drive)); return 0; } @@ -2050,7 +2125,8 @@ static int idefloppy_attach (ide_drive_t *drive) { idefloppy_floppy_t *floppy; - struct gendisk *g = drive->disk; + struct gendisk *g; + if (!strstr("ide-floppy", drive->driver_req)) goto failed; if (!drive->present) @@ -2069,11 +2145,30 @@ printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } + + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_free_floppy; + + ide_init_disk(g, drive); + if (ide_register_subdriver(drive, &idefloppy_driver)) { printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (floppy); - goto failed; + goto out_put_disk; } + + memset(floppy, 0, sizeof(*floppy)); + + kref_init(&floppy->kref); + + floppy->drive = drive; + floppy->driver = &idefloppy_driver; + floppy->disk = g; + + g->private_data = &floppy->driver; + + drive->driver_data = floppy; + DRIVER(drive)->busy++; idefloppy_setup (drive, floppy); DRIVER(drive)->busy--; @@ -2085,6 +2180,11 @@ drive->attach = 1; add_disk(g); return 0; + +out_put_disk: + put_disk(g); +out_free_floppy: + kfree(floppy); failed: return 1; } diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-io.c 2005-02-28 17:22:05 -08:00 @@ -189,6 +189,100 @@ } EXPORT_SYMBOL(ide_end_request); +/* + * Power Management state machine. This one is rather trivial for now, + * we should probably add more, like switching back to PIO on suspend + * to help some BIOSes, re-do the door locking on resume, etc... + */ + +enum { + ide_pm_flush_cache = ide_pm_state_start_suspend, + idedisk_pm_standby, + + idedisk_pm_idle = ide_pm_state_start_resume, + ide_pm_restore_dma, +}; + +static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) +{ + if (drive->media != ide_disk) + return; + + switch (rq->pm->pm_step) { + case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ + if (rq->pm->pm_state == 4) + rq->pm->pm_step = ide_pm_state_completed; + else + rq->pm->pm_step = idedisk_pm_standby; + break; + case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ + rq->pm->pm_step = ide_pm_state_completed; + break; + case idedisk_pm_idle: /* Resume step 1 (idle) complete */ + rq->pm->pm_step = ide_pm_restore_dma; + break; + } +} + +static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) +{ + ide_task_t *args = rq->special; + + memset(args, 0, sizeof(*args)); + + if (drive->media != ide_disk) { + /* skip idedisk_pm_idle for ATAPI devices */ + if (rq->pm->pm_step == idedisk_pm_idle) + rq->pm->pm_step = ide_pm_restore_dma; + } + + switch (rq->pm->pm_step) { + case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ + if (drive->media != ide_disk) + break; + /* Not supported? Switch to next step now. */ + if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { + ide_complete_power_step(drive, rq, 0, 0); + return ide_stopped; + } + if (ide_id_has_flush_cache_ext(drive->id)) { + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + args->flags |= ATA_TFLAG_LBA48; + } else + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = &task_no_data_intr; + return do_rw_taskfile(drive, args); + + case idedisk_pm_standby: /* Suspend step 2 (standby) */ + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = &task_no_data_intr; + return do_rw_taskfile(drive, args); + + case idedisk_pm_idle: /* Resume step 1 (idle) */ + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = task_no_data_intr; + return do_rw_taskfile(drive, args); + + case ide_pm_restore_dma: /* Resume step 2 (restore DMA) */ + /* + * Right now, all we do is call hwif->ide_dma_check(drive), + * we could be smarter and check for current xfer_speed + * in struct drive etc... + */ + if ((drive->id->capability & 1) == 0) + break; + if (drive->hwif->ide_dma_check == NULL) + break; + drive->hwif->ide_dma_check(drive); + break; + } + rq->pm->pm_step = ide_pm_state_completed; + return ide_stopped; +} + /** * ide_complete_pm_request - end the current Power Management request * @drive: target drive @@ -395,7 +489,7 @@ args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); args->tfRegister[IDE_STATUS_OFFSET] = stat; - if (drive->addressing == 1) { + if (args->flags & ATA_TFLAG_LBA48) { hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG); args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); @@ -409,7 +503,7 @@ printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", drive->name, rq->pm->pm_step, stat, err); #endif - DRIVER(drive)->complete_power_step(drive, rq, stat, err); + ide_complete_power_step(drive, rq, stat, err); if (rq->pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return; @@ -453,6 +547,17 @@ } } +static void ide_kill_rq(ide_drive_t *drive, struct request *rq) +{ + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + drv->end_request(drive, 0, 0); + } else + ide_end_request(drive, 0, 0); +} + static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) { ide_hwif_t *hwif = drive->hwif; @@ -487,7 +592,7 @@ hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) - drive->driver->end_request(drive, 0, 0); + ide_kill_rq(drive, rq); else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -516,7 +621,7 @@ hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); if (rq->errors >= ERROR_MAX) { - drive->driver->end_request(drive, 0, 0); + ide_kill_rq(drive, rq); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -536,6 +641,8 @@ return ide_atapi_error(drive, rq, stat, err); } +EXPORT_SYMBOL_GPL(__ide_error); + /** * ide_error - handle an error on the IDE * @drive: drive the error occurred on @@ -566,7 +673,13 @@ return ide_stopped; } - return drive->driver->error(drive, rq, stat, err); + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + return drv->error(drive, rq, stat, err); + } else + return __ide_error(drive, rq, stat, err); } EXPORT_SYMBOL_GPL(ide_error); @@ -576,10 +689,13 @@ if (drive->media != ide_disk) rq->errors |= ERROR_RESET; - DRIVER(drive)->end_request(drive, 0, 0); + ide_kill_rq(drive, rq); + return ide_stopped; } +EXPORT_SYMBOL_GPL(__ide_abort); + /** * ide_abort - abort pending IDE operatins * @drive: drive the error occurred on @@ -608,7 +724,13 @@ return ide_stopped; } - return drive->driver->abort(drive, rq); + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + return drv->abort(drive, rq); + } else + return __ide_abort(drive, rq); } /** @@ -661,13 +783,72 @@ udelay(100); } - if (!OK_STAT(stat, READY_STAT, BAD_STAT) && DRIVER(drive) != NULL) + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped; } +static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl; + task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; + task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; + + task->handler = &set_geometry_intr; +} + +static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; + + task->handler = &recal_intr; +} + +static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; + + task->handler = &set_multmode_intr; +} + +static ide_startstop_t ide_disk_special(ide_drive_t *drive) +{ + special_t *s = &drive->special; + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.command_type = IDE_DRIVE_TASK_NO_DATA; + + if (s->b.set_geometry) { + s->b.set_geometry = 0; + ide_init_specify_cmd(drive, &args); + } else if (s->b.recalibrate) { + s->b.recalibrate = 0; + ide_init_restore_cmd(drive, &args); + } else if (s->b.set_multmode) { + s->b.set_multmode = 0; + if (drive->mult_req > drive->id->max_multsect) + drive->mult_req = drive->id->max_multsect; + ide_init_setmult_cmd(drive, &args); + } else if (s->all) { + int special = s->all; + s->all = 0; + printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); + return ide_stopped; + } + + do_rw_taskfile(drive, &args); + + return ide_started; +} + /** * do_special - issue some special commands * @drive: drive the command is for @@ -689,9 +870,14 @@ if (HWIF(drive)->tuneproc != NULL) HWIF(drive)->tuneproc(drive, drive->tune_req); return ide_stopped; + } else { + if (drive->media == ide_disk) + return ide_disk_special(drive); + + s->all = 0; + drive->mult_req = 0; + return ide_stopped; } - else - return DRIVER(drive)->special(drive); } void ide_map_sg(ide_drive_t *drive, struct request *rq) @@ -897,6 +1083,8 @@ return startstop; } if (!drive->special.all) { + ide_driver_t *drv; + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) return execute_drive_cmd(drive, rq); else if (rq->flags & REQ_DRIVE_TASKFILE) @@ -906,17 +1094,19 @@ printk("%s: start_power_step(step: %d)\n", drive->name, rq->pm->pm_step); #endif - startstop = DRIVER(drive)->start_power_step(drive, rq); + startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && rq->pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return startstop; } - return (DRIVER(drive)->do_request(drive, rq, block)); + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + return drv->do_request(drive, rq, block); } return do_special(drive); kill_rq: - DRIVER(drive)->end_request(drive, 0, 0); + ide_kill_rq(drive, rq); return ide_stopped; } @@ -1597,8 +1787,6 @@ rq->errors = 0; rq->rq_status = RQ_ACTIVE; - - rq->rq_disk = drive->disk; /* * we need to hold an extra reference to request for safe inspection diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-iops.c 2005-02-28 17:22:05 -08:00 @@ -1107,9 +1107,27 @@ #endif } +static void ide_disk_pre_reset(ide_drive_t *drive) +{ + int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; + + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; + if (OK_TO_RESET_CONTROLLER) + drive->mult_count = 0; + if (!drive->keep_settings && !drive->using_dma) + drive->mult_req = 0; + if (drive->mult_req != drive->mult_count) + drive->special.b.set_multmode = 1; +} + static void pre_reset(ide_drive_t *drive) { - DRIVER(drive)->pre_reset(drive); + if (drive->media == ide_disk) + ide_disk_pre_reset(drive); + else + drive->post_reset = 1; if (!drive->keep_settings) { if (drive->using_dma) { diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-probe.c 2005-02-28 17:22:05 -08:00 @@ -74,7 +74,55 @@ drive->id->cur_heads = drive->head; drive->id->cur_sectors = drive->sect; } - + +static void ide_disk_init_chs(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + /* Extract geometry if we did not already have one for the drive */ + if (!drive->cyl || !drive->head || !drive->sect) { + drive->cyl = drive->bios_cyl = id->cyls; + drive->head = drive->bios_head = id->heads; + drive->sect = drive->bios_sect = id->sectors; + } + + /* Handle logical geometry translation by the drive */ + if ((id->field_valid & 1) && id->cur_cyls && + id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { + drive->cyl = id->cur_cyls; + drive->head = id->cur_heads; + drive->sect = id->cur_sectors; + } + + /* Use physical geometry if what we have still makes no sense */ + if (drive->head > 16 && id->heads && id->heads <= 16) { + drive->cyl = id->cyls; + drive->head = id->heads; + drive->sect = id->sectors; + } +} + +static void ide_disk_init_mult_count(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + drive->mult_count = 0; + if (id->max_multsect) { +#ifdef CONFIG_IDEDISK_MULTI_MODE + id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; + id->multsect_valid = id->multsect ? 1 : 0; + drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; + drive->special.b.set_multmode = drive->mult_req ? 1 : 0; +#else /* original, pre IDE-NFG, per request of AC */ + drive->mult_req = INITIAL_MULT_COUNT; + if (drive->mult_req > id->max_multsect) + drive->mult_req = id->max_multsect; + if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) + drive->special.b.set_multmode = 1; +#endif + } +} + /** * drive_is_flashcard - check for compact flash * @drive: drive to check @@ -221,6 +269,8 @@ } printk (" drive\n"); drive->media = type; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; return; } @@ -588,8 +638,16 @@ if(!drive->present) return 0; /* The drive wasn't being helpful. Add generic info only */ - if(!drive->id_read) + if (drive->id_read == 0) { generic_id(drive); + return 1; + } + + if (drive->media == ide_disk) { + ide_disk_init_chs(drive); + ide_disk_init_mult_count(drive); + } + return drive->present; } @@ -804,6 +862,13 @@ drive->autotune == IDE_TUNE_AUTO) /* auto-tune PIO mode */ hwif->tuneproc(drive, 255); + + if (drive->autotune != IDE_TUNE_DEFAULT && + drive->autotune != IDE_TUNE_AUTO) + continue; + + drive->nice1 = 1; + /* * MAJOR HACK BARF :-/ * @@ -813,9 +878,7 @@ * Move here to prevent module loading clashing. */ // drive->autodma = hwif->autodma; - if ((hwif->ide_dma_check) && - ((drive->autotune == IDE_TUNE_DEFAULT) || - (drive->autotune == IDE_TUNE_AUTO))) { + if (hwif->ide_dma_check) { /* * Force DMAing for the beginning of the check. * Some chipsets appear to do interesting @@ -948,10 +1011,8 @@ blk_queue_max_hw_segments(q, max_sg_entries); blk_queue_max_phys_segments(q, max_sg_entries); - /* assign drive and gendisk queue */ + /* assign drive queue */ drive->queue = q; - if (drive->disk) - drive->disk->queue = drive->queue; /* needs drive->queue to be set */ ide_toggle_bounce(drive, 1); @@ -1151,8 +1212,6 @@ return 0; } -extern ide_driver_t idedefault_driver; - static struct kobject *ata_probe(dev_t dev, int *part, void *data) { ide_hwif_t *hwif = data; @@ -1160,52 +1219,66 @@ ide_drive_t *drive = &hwif->drives[unit]; if (!drive->present) return NULL; - if (drive->driver == &idedefault_driver) { - if (drive->media == ide_disk) - (void) request_module("ide-disk"); - if (drive->scsi) - (void) request_module("ide-scsi"); - if (drive->media == ide_cdrom || drive->media == ide_optical) - (void) request_module("ide-cd"); - if (drive->media == ide_tape) - (void) request_module("ide-tape"); - if (drive->media == ide_floppy) - (void) request_module("ide-floppy"); - } - if (drive->driver == &idedefault_driver) - return NULL; + + if (drive->media == ide_disk) + request_module("ide-disk"); + if (drive->scsi) + request_module("ide-scsi"); + if (drive->media == ide_cdrom || drive->media == ide_optical) + request_module("ide-cd"); + if (drive->media == ide_tape) + request_module("ide-tape"); + if (drive->media == ide_floppy) + request_module("ide-floppy"); + + return NULL; +} + +static struct kobject *exact_match(dev_t dev, int *part, void *data) +{ + struct gendisk *p = data; *part &= (1 << PARTN_BITS) - 1; - return get_disk(drive->disk); + return &p->kobj; } -static int alloc_disks(ide_hwif_t *hwif) +static int exact_lock(dev_t dev, void *data) { - unsigned int unit; - struct gendisk *disks[MAX_DRIVES]; + struct gendisk *p = data; - for (unit = 0; unit < MAX_DRIVES; unit++) { - disks[unit] = alloc_disk(1 << PARTN_BITS); - if (!disks[unit]) - goto Enomem; - } - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - struct gendisk *disk = disks[unit]; - disk->major = hwif->major; - disk->first_minor = unit << PARTN_BITS; - sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit); - disk->fops = ide_fops; - disk->private_data = drive; - drive->disk = disk; - } + if (!get_disk(p)) + return -1; return 0; -Enomem: - printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n"); - while (unit--) - put_disk(disks[unit]); - return -ENOMEM; } +void ide_register_region(struct gendisk *disk) +{ + blk_register_region(MKDEV(disk->major, disk->first_minor), + disk->minors, NULL, exact_match, exact_lock, disk); +} + +EXPORT_SYMBOL_GPL(ide_register_region); + +void ide_unregister_region(struct gendisk *disk) +{ + blk_unregister_region(MKDEV(disk->major, disk->first_minor), + disk->minors); +} + +EXPORT_SYMBOL_GPL(ide_unregister_region); + +void ide_init_disk(struct gendisk *disk, ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned int unit = drive->select.all & (1 << 4); + + disk->major = hwif->major; + disk->first_minor = unit << PARTN_BITS; + sprintf(disk->disk_name, "hd%c", 'a' + hwif->index * MAX_DRIVES + unit); + disk->queue = drive->queue; +} + +EXPORT_SYMBOL_GPL(ide_init_disk); + static void drive_release_dev (struct device *dev) { ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); @@ -1246,7 +1319,7 @@ static int hwif_init(ide_hwif_t *hwif) { - int old_irq, unit; + int old_irq; /* Return success if no device is connected */ if (!hwif->present) @@ -1282,9 +1355,6 @@ printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); goto out; } - - if (alloc_disks(hwif) < 0) - goto out; if (init_irq(hwif) == 0) goto done; @@ -1297,12 +1367,12 @@ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, old_irq); - goto out_disks; + goto out; } if (init_irq(hwif)) { printk("%s: probed IRQ %d and default IRQ %d failed.\n", hwif->name, old_irq, hwif->irq); - goto out_disks; + goto out; } printk("%s: probed IRQ %d failed, using default.\n", hwif->name, hwif->irq); @@ -1312,12 +1382,6 @@ hwif->present = 1; /* success */ return 1; -out_disks: - for (unit = 0; unit < MAX_DRIVES; unit++) { - struct gendisk *disk = hwif->drives[unit].disk; - hwif->drives[unit].disk = NULL; - put_disk(disk); - } out: unregister_blkdev(hwif->major, hwif->name); return 0; diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c --- a/drivers/ide/ide-proc.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-proc.c 2005-02-28 17:22:05 -08:00 @@ -107,8 +107,6 @@ if (drive) { unsigned short *val = (unsigned short *) page; - BUG_ON(!drive->driver); - err = taskfile_lib_get_identify(drive, page); if (!err) { char *out = ((char *)page) + (SECTOR_WORDS * 4); @@ -269,14 +267,12 @@ int proc_ide_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_drive_t *drive = (ide_drive_t *) data; - int len; - - len = sprintf(page,"%llu\n", - (long long) (DRIVER(drive)->capacity(drive))); + int len = sprintf(page,"%llu\n", (long long)0x7fffffff); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +EXPORT_SYMBOL_GPL(proc_ide_read_capacity); + int proc_ide_read_geometry (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -314,8 +310,11 @@ ide_driver_t *driver = drive->driver; int len; - len = sprintf(page, "%s version %s\n", - driver->name, driver->version); + if (driver) { + len = sprintf(page, "%s version %s\n", + driver->name, driver->version); + } else + len = sprintf(page, "ide-default version 0.9.newide\n"); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -423,10 +422,7 @@ static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) { - ide_driver_t *driver = drive->driver; - if (drive->proc) { - ide_remove_proc_entries(drive->proc, driver->proc); ide_remove_proc_entries(drive->proc, generic_drive_entries); remove_proc_entry(drive->name, proc_ide_root); remove_proc_entry(drive->name, hwif->proc); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-tape.c 2005-02-28 17:22:05 -08:00 @@ -781,8 +781,12 @@ * driver due to an interrupt or a timer event is stored in a variable * of type idetape_tape_t, defined below. */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_tape_obj { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct kref kref; + /* * Since a typical character device operation requires more * than one packet command, we provide here enough memory @@ -1007,6 +1011,34 @@ int debug_level; } idetape_tape_t; +static DECLARE_MUTEX(idetape_ref_sem); + +#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref) + +#define ide_tape_g(disk) \ + container_of((disk)->private_data, struct ide_tape_obj, driver) + +static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) +{ + struct ide_tape_obj *tape = NULL; + + down(&idetape_ref_sem); + tape = ide_tape_g(disk); + if (tape) + kref_get(&tape->kref); + up(&idetape_ref_sem); + return tape; +} + +static void ide_tape_release(struct kref *); + +static void ide_tape_put(struct ide_tape_obj *tape) +{ + down(&idetape_ref_sem); + kref_put(&tape->kref, ide_tape_release); + up(&idetape_ref_sem); +} + /* * Tape door status */ @@ -1093,15 +1125,6 @@ #define IDETAPE_ERROR_EOD 103 /* - * idetape_chrdev_t provides the link between out character device - * interface and our block device interface and the corresponding - * ide_drive_t structure. - */ -typedef struct { - ide_drive_t *drive; -} idetape_chrdev_t; - -/* * The following is used to format the general configuration word of * the ATAPI IDENTIFY DEVICE command. */ @@ -1257,7 +1280,21 @@ * The variables below are used for the character device interface. * Additional state variables are defined in our ide_drive_t structure. */ -static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES]; +static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES]; + +#define ide_tape_f(file) ((file)->private_data) + +static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) +{ + struct ide_tape_obj *tape = NULL; + + down(&idetape_ref_sem); + tape = idetape_devs[i]; + if (tape) + kref_get(&tape->kref); + up(&idetape_ref_sem); + return tape; +} /* * Function declarations @@ -1509,6 +1546,7 @@ } #endif /* IDETAPE_DEBUG_BUGS */ + rq->rq_disk = tape->disk; rq->buffer = NULL; rq->special = (void *)stage->bh; tape->active_data_request = rq; @@ -1761,8 +1799,11 @@ */ static void idetape_queue_pc_head (ide_drive_t *drive, idetape_pc_t *pc,struct request *rq) { + struct ide_tape_obj *tape = drive->driver_data; + idetape_init_rq(rq, REQ_IDETAPE_PC1); rq->buffer = (char *) pc; + rq->rq_disk = tape->disk; (void) ide_do_drive_cmd(drive, rq, ide_preempt); } @@ -2428,6 +2469,11 @@ if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + if (drive->post_reset == 1) { + set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + drive->post_reset = 0; + } + if (tape->tape_still_time > 100 && tape->tape_still_time < 200) tape->measure_insert_time = 1; if (time_after(jiffies, tape->insert_time)) @@ -2812,10 +2858,12 @@ */ static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc) { + struct ide_tape_obj *tape = drive->driver_data; struct request rq; idetape_init_rq(&rq, REQ_IDETAPE_PC1); rq.buffer = (char *) pc; + rq.rq_disk = tape->disk; return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -3039,6 +3087,7 @@ #endif /* IDETAPE_DEBUG_BUGS */ idetape_init_rq(&rq, cmd); + rq.rq_disk = tape->disk; rq.special = (void *)bh; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; @@ -3558,16 +3607,6 @@ } /* - * idetape_pre_reset is called before an ATAPI/ATA software reset. - */ -static void idetape_pre_reset (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - if (tape != NULL) - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); -} - -/* * idetape_space_over_filemarks is now a bit more complicated than just * passing the command to the tape since we may have crossed some * filemarks during our pipelined read-ahead mode. @@ -3673,8 +3712,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; ssize_t bytes_read,temp, actually_read = 0, rc; #if IDETAPE_DEBUG_LOG @@ -3732,8 +3771,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; ssize_t retval, actually_written = 0; /* The drive is write protected. */ @@ -4035,8 +4074,8 @@ */ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; struct mtop mtop; struct mtget mtget; struct mtpos mtpos; @@ -4107,17 +4146,24 @@ if (i >= MAX_HWIFS * MAX_DRIVES) return -ENXIO; - drive = idetape_chrdevs[i].drive; - tape = drive->driver_data; - filp->private_data = drive; - if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) - return -EBUSY; + if (!(tape = ide_tape_chrdev_get(i))) + return -ENXIO; + + drive = tape->drive; + + filp->private_data = tape; + + if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) { + retval = -EBUSY; + goto out_put_tape; + } + retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { clear_bit(IDETAPE_BUSY, &tape->flags); printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); - return retval; + goto out_put_tape; } idetape_read_position(drive); @@ -4141,7 +4187,8 @@ if ((filp->f_flags & O_ACCMODE) == O_WRONLY || (filp->f_flags & O_ACCMODE) == O_RDWR) { clear_bit(IDETAPE_BUSY, &tape->flags); - return -EROFS; + retval = -EROFS; + goto out_put_tape; } } @@ -4159,6 +4206,10 @@ idetape_restart_speed_control(drive); tape->restart_speed_control_req = 0; return 0; + +out_put_tape: + ide_tape_put(tape); + return retval; } static void idetape_write_release (ide_drive_t *drive, unsigned int minor) @@ -4182,8 +4233,8 @@ */ static int idetape_chrdev_release (struct inode *inode, struct file *filp) { - ide_drive_t *drive = filp->private_data; - idetape_tape_t *tape; + struct ide_tape_obj *tape = ide_tape_f(filp); + ide_drive_t *drive = tape->drive; idetape_pc_t pc; unsigned int minor = iminor(inode); @@ -4217,6 +4268,7 @@ } } clear_bit(IDETAPE_BUSY, &tape->flags); + ide_tape_put(tape); unlock_kernel(); return 0; } @@ -4527,11 +4579,7 @@ int stage_size; struct sysinfo si; - memset(tape, 0, sizeof (idetape_tape_t)); spin_lock_init(&tape->spinlock); - drive->driver_data = tape; - /* An ATAPI device ignores DRDY */ - drive->ready_stat = 0; drive->dsc_overlap = 1; #ifdef CONFIG_BLK_DEV_IDEPCI if (HWIF(drive)->pci_dev != NULL) { @@ -4549,7 +4597,6 @@ /* Seagate Travan drives do not support DSC overlap. */ if (strstr(drive->id->model, "Seagate STT3401")) drive->dsc_overlap = 0; - tape->drive = drive; tape->minor = minor; tape->name[0] = 'h'; tape->name[1] = 't'; @@ -4630,7 +4677,6 @@ static int idetape_cleanup (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - int minor = tape->minor; unsigned long flags; spin_lock_irqsave(&ide_lock, flags); @@ -4639,17 +4685,33 @@ spin_unlock_irqrestore(&ide_lock, flags); return 1; } - idetape_chrdevs[minor].drive = NULL; + spin_unlock_irqrestore(&ide_lock, flags); DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver(drive); + + ide_unregister_region(tape->disk); + + ide_tape_put(tape); + + return 0; +} + +static void ide_tape_release(struct kref *kref) +{ + struct ide_tape_obj *tape = to_ide_tape(kref); + ide_drive_t *drive = tape->drive; + struct gendisk *g = tape->disk; + + drive->dsc_overlap = 0; drive->driver_data = NULL; devfs_remove("%s/mt", drive->devfs_name); devfs_remove("%s/mtn", drive->devfs_name); - devfs_unregister_tape(drive->disk->number); - kfree (tape); - drive->disk->fops = ide_fops; - return 0; + devfs_unregister_tape(g->number); + idetape_devs[tape->minor] = NULL; + g->private_data = NULL; + put_disk(g); + kfree(tape); } #ifdef CONFIG_PROC_FS @@ -4667,6 +4729,7 @@ } static ide_proc_entry_t idetape_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, { NULL, 0, NULL, NULL } }; @@ -4692,7 +4755,8 @@ .cleanup = idetape_cleanup, .do_request = idetape_do_request, .end_request = idetape_end_request, - .pre_reset = idetape_pre_reset, + .error = __ide_error, + .abort = __ide_abort, .proc = idetape_proc, .attach = idetape_attach, .drives = LIST_HEAD_INIT(idetape_driver.drives), @@ -4712,15 +4776,30 @@ static int idetape_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_tape_obj *tape; + ide_drive_t *drive; + + if (!(tape = ide_tape_get(disk))) + return -ENXIO; + + drive = tape->drive; + drive->usage++; + return 0; } static int idetape_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_tape_obj *tape = ide_tape_g(disk); + ide_drive_t *drive = tape->drive; + drive->usage--; + + ide_tape_put(tape); + return 0; } @@ -4728,8 +4807,9 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - int err = generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk); + ide_drive_t *drive = tape->drive; + int err = generic_ide_ioctl(drive, file, bdev, cmd, arg); if (err == -EINVAL) err = idetape_blkdev_ioctl(drive, cmd, arg); return err; @@ -4745,6 +4825,7 @@ static int idetape_attach (ide_drive_t *drive) { idetape_tape_t *tape; + struct gendisk *g; int minor; if (!strstr("ide-tape", drive->driver_req)) @@ -4770,15 +4851,37 @@ printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; } + + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_free_tape; + + ide_init_disk(g, drive); + if (ide_register_subdriver(drive, &idetape_driver)) { printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree(tape); - goto failed; + goto out_put_disk; } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++) + + memset(tape, 0, sizeof(*tape)); + + kref_init(&tape->kref); + + tape->drive = drive; + tape->driver = &idetape_driver; + tape->disk = g; + + g->private_data = &tape->driver; + + drive->driver_data = tape; + + down(&idetape_ref_sem); + for (minor = 0; idetape_devs[minor]; minor++) ; + idetape_devs[minor] = tape; + up(&idetape_ref_sem); + idetape_setup(drive, tape, minor); - idetape_chrdevs[minor].drive = drive; devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), S_IFCHR | S_IRUGO | S_IWUGO, @@ -4787,9 +4890,15 @@ S_IFCHR | S_IRUGO | S_IWUGO, "%s/mtn", drive->devfs_name); - drive->disk->number = devfs_register_tape(drive->devfs_name); - drive->disk->fops = &idetape_block_ops; + g->number = devfs_register_tape(drive->devfs_name); + g->fops = &idetape_block_ops; + ide_register_region(g); + return 0; +out_put_disk: + put_disk(g); +out_free_tape: + kfree(tape); failed: return 1; } diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide-taskfile.c 2005-02-28 17:22:05 -08:00 @@ -101,7 +101,7 @@ ide_hwif_t *hwif = HWIF(drive); task_struct_t *taskfile = (task_struct_t *) task->tfRegister; hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; + u8 HIHI = (task->flags & ATA_TFLAG_LBA48) ? 0xE0 : 0xEF; /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ if (IDE_CONTROL_REG) { @@ -110,7 +110,7 @@ } SELECT_MASK(drive, 0); - if (drive->addressing == 1) { + if (task->flags & ATA_TFLAG_LBA48) { hwif->OUTB(hobfile->feature, IDE_FEATURE_REG); hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); @@ -181,8 +181,6 @@ return ide_stopped; } -EXPORT_SYMBOL(set_multmode_intr); - /* * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. */ @@ -207,8 +205,6 @@ return ide_started; } -EXPORT_SYMBOL(set_geometry_intr); - /* * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. */ @@ -222,8 +218,6 @@ return ide_stopped; } -EXPORT_SYMBOL(recal_intr); - /* * Handler for commands without a data phase */ @@ -321,9 +315,18 @@ static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { + u8 saved_io_32bit = drive->io_32bit; + if (rq->bio) /* fs request */ rq->errors = 0; + if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *task = rq->special; + + if (task->flags & ATA_TFLAG_IO_16BIT) + drive->io_32bit = 0; + } + switch (drive->hwif->data_phase) { case TASKFILE_MULTI_IN: case TASKFILE_MULTI_OUT: @@ -333,6 +336,8 @@ ide_pio_sector(drive, write); break; } + + drive->io_32bit = saved_io_32bit; } static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, @@ -360,8 +365,12 @@ break; } - if (sectors > 0) - drive->driver->end_request(drive, 1, sectors); + if (sectors > 0) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + drv->end_request(drive, 1, sectors); + } } return ide_error(drive, s, stat); } @@ -377,7 +386,8 @@ return; } } - drive->driver->end_request(drive, 1, rq->hard_nr_sectors); + + ide_end_request(drive, 1, rq->hard_nr_sectors); } /* @@ -523,7 +533,6 @@ int tasksize = sizeof(struct ide_task_request_s); int taskin = 0; int taskout = 0; - u8 io_32bit = drive->io_32bit; char __user *buf = (char __user *)arg; // printk("IDE Taskfile ...\n"); @@ -576,7 +585,10 @@ args.data_phase = req_task->data_phase; args.command_type = req_task->req_cmd; - drive->io_32bit = 0; + args.flags = ATA_TFLAG_IO_16BIT; + if (drive->addressing == 1) + args.flags |= ATA_TFLAG_LBA48; + switch(req_task->data_phase) { case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: @@ -655,8 +667,6 @@ kfree(inbuf); // printk("IDE Taskfile ioctl ended. rc = %i\n", err); - - drive->io_32bit = io_32bit; return err; } diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/ide.c 2005-02-28 17:22:05 -08:00 @@ -196,8 +196,7 @@ EXPORT_SYMBOL(ide_hwifs); -extern ide_driver_t idedefault_driver; -static void setup_driver_defaults(ide_driver_t *driver); +static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives); /* * Do not even *think* about calling this! @@ -246,7 +245,6 @@ drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->using_dma = 0; drive->is_flash = 0; - drive->driver = &idedefault_driver; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); sema_init(&drive->gendev_rel_sem, 0); @@ -301,8 +299,6 @@ return; /* already initialized */ magic_cookie = 0; - setup_driver_defaults(&idedefault_driver); - /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; @@ -362,11 +358,6 @@ return system_bus_speed; } -static int ide_open (struct inode * inode, struct file * filp) -{ - return -ENXIO; -} - /* * drives_lock protects the list of drives, drivers_lock the * list of drivers. Currently nobody takes both at once. @@ -417,11 +408,6 @@ #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_ide_root; - -static ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; #endif static struct resource* hwif_request_region(ide_hwif_t *hwif, @@ -771,11 +757,6 @@ * Remove us from the kernel's knowledge */ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<drives[i].disk; - hwif->drives[i].disk = NULL; - put_disk(disk); - } kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); @@ -939,7 +920,7 @@ DECLARE_MUTEX(ide_setting_sem); /** - * ide_add_setting - add an ide setting option + * __ide_add_setting - add an ide setting option * @drive: drive to use * @name: setting name * @rw: true if the function is read write @@ -952,6 +933,7 @@ * @div_factor: divison scale * @data: private data field * @set: setting + * @auto_remove: setting auto removal flag * * Removes the setting named from the device if it is present. * The function takes the settings_lock to protect against @@ -963,8 +945,8 @@ * a driver is attached we assume the driver settings are auto * remove. */ - -int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; @@ -989,7 +971,7 @@ setting->set = set; setting->next = *p; - if (drive->driver != &idedefault_driver) + if (auto_remove) setting->auto_remove = 1; *p = setting; up(&ide_setting_sem); @@ -1001,6 +983,11 @@ return -1; } +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + EXPORT_SYMBOL(ide_add_setting); /** @@ -1290,17 +1277,17 @@ void ide_add_generic_settings (ide_drive_t *drive) { /* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit); - ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); - ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); - ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); - ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate); - ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } /** @@ -1338,7 +1325,7 @@ } else { drive->driver_req[0] = 0; } - if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver)) + if (drive->driver && !strcmp(drive->driver->name, driver)) return 0; abort: return 1; @@ -1377,9 +1364,9 @@ spin_lock(&drivers_lock); module_put(driver->owner); } - drive->gendev.driver = &idedefault_driver.gen_driver; + drive->gendev.driver = NULL; spin_unlock(&drivers_lock); - if(idedefault_driver.attach(drive) != 0) + if (ide_register_subdriver(drive, NULL)) panic("ide: default attach failed"); return 1; } @@ -1422,11 +1409,11 @@ return ide_do_drive_cmd(drive, &rq, ide_head_wait); } -int generic_ide_ioctl(struct file *file, struct block_device *bdev, +int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = bdev->bd_disk->private_data; ide_settings_t *setting; + ide_driver_t *drv; int err = 0; void __user *p = (void __user *)arg; @@ -1526,7 +1513,8 @@ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { + drv = *(ide_driver_t **)bdev->bd_disk->private_data; + if (drive->dsc_overlap && !drv->supports_dsc_overlap) { drive->dsc_overlap = 0; return -EPERM; } @@ -1751,6 +1739,8 @@ case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; hwif->noprobe = 0; goto done; case -5: /* "serialize" */ @@ -2022,76 +2012,12 @@ #endif } -static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) -{ - ide_end_request(drive, 0, 0); - return ide_stopped; -} - -static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects) -{ - return ide_end_request(drive, uptodate, nr_sects); -} - -static ide_startstop_t -default_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - return __ide_error(drive, rq, stat, err); -} - -static void default_pre_reset (ide_drive_t *drive) -{ -} - -static sector_t default_capacity (ide_drive_t *drive) -{ - return 0x7fffffff; -} - -static ide_startstop_t default_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} - -static ide_startstop_t default_abort(ide_drive_t *drive, struct request *rq) -{ - return __ide_abort(drive, rq); -} - -static ide_startstop_t default_start_power_step(ide_drive_t *drive, - struct request *rq) -{ - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; -} - -static void setup_driver_defaults (ide_driver_t *d) -{ - BUG_ON(d->attach == NULL || d->cleanup == NULL); - - if (d->do_request == NULL) d->do_request = default_do_request; - if (d->end_request == NULL) d->end_request = default_end_request; - if (d->error == NULL) d->error = default_error; - if (d->abort == NULL) d->abort = default_abort; - if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; - if (d->capacity == NULL) d->capacity = default_capacity; - if (d->special == NULL) d->special = default_special; - if (d->start_power_step == NULL) - d->start_power_step = default_start_power_step; -} - int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; - BUG_ON(!drive->driver); - spin_lock_irqsave(&ide_lock, flags); - if (!drive->present || drive->driver != &idedefault_driver || + if (!drive->present || drive->driver != NULL || drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; @@ -2099,20 +2025,12 @@ drive->driver = driver; spin_unlock_irqrestore(&ide_lock, flags); spin_lock(&drives_lock); - list_add_tail(&drive->list, &driver->drives); + list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives); spin_unlock(&drives_lock); // printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); - if ((drive->autotune == IDE_TUNE_DEFAULT) || - (drive->autotune == IDE_TUNE_AUTO)) { - /* DMA timings and setup moved to ide-probe.c */ - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); - drive->nice1 = 1; - } #ifdef CONFIG_PROC_FS - if (drive->driver != &idedefault_driver) { - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); + if (driver) ide_add_proc_entries(drive->proc, driver->proc, drive); - } #endif return 0; } @@ -2139,23 +2057,22 @@ down(&ide_setting_sem); spin_lock_irqsave(&ide_lock, flags); - if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) { + if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); return 1; } #ifdef CONFIG_PROC_FS ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); #endif auto_remove_settings(drive); - drive->driver = &idedefault_driver; + drive->driver = NULL; spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); spin_lock(&drives_lock); list_del_init(&drive->list); spin_unlock(&drives_lock); - /* drive will be added to &idedefault_driver->drives in ata_attach() */ + /* drive will be added to &ide_drives in ata_attach() */ return 0; } @@ -2185,15 +2102,13 @@ struct list_head *list_loop; struct list_head *tmp_storage; - setup_driver_defaults(driver); - spin_lock(&drivers_lock); list_add(&driver->drivers, &drivers); spin_unlock(&drivers_lock); INIT_LIST_HEAD(&list); spin_lock(&drives_lock); - list_splice_init(&idedefault_driver.drives, &list); + list_splice_init(&ide_drives, &list); spin_unlock(&drives_lock); list_for_each_safe(list_loop, tmp_storage, &list) { @@ -2242,13 +2157,6 @@ } EXPORT_SYMBOL(ide_unregister_driver); - -struct block_device_operations ide_fops[] = {{ - .owner = THIS_MODULE, - .open = ide_open, -}}; - -EXPORT_SYMBOL(ide_fops); /* * Probe module diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/pci/pdc202xx_new.c 2005-02-28 17:22:05 -08:00 @@ -420,9 +420,6 @@ .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 3 */ .name = "PDC20271", @@ -447,9 +444,6 @@ .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 6 */ .name = "PDC20277", diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/pci/pdc202xx_old.c 2005-02-28 17:22:05 -08:00 @@ -786,9 +786,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 16, },{ /* 1 */ @@ -799,12 +796,8 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -813,9 +806,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, },{ /* 3 */ @@ -826,12 +816,8 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, @@ -840,9 +826,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, } diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/pci/via82cxxx.c 2005-02-28 17:22:05 -08:00 @@ -79,6 +79,7 @@ u8 rev_max; u16 flags; } via_isa_bridges[] = { + { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, @@ -332,11 +333,8 @@ struct ide_timing t, p; unsigned int T, UT; - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't " - "accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); + if (speed != XFER_PIO_SLOW) + ide_config_drive_speed(drive, speed); T = 1000000000 / via_clock; @@ -619,24 +617,35 @@ hwif->drives[1].autodma = hwif->autodma; } -static ide_pci_device_t via82cxxx_chipset __devinitdata = { - .name = "VP_IDE", - .init_chipset = init_chipset_via82cxxx, - .init_hwif = init_hwif_via82cxxx, - .channels = 2, - .autodma = NOAUTODMA, - .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, - .bootable = ON_BOARD, +static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { + { /* 0 */ + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_hwif = init_hwif_via82cxxx, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD + },{ /* 1 */ + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_hwif = init_hwif_via82cxxx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + } }; static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &via82cxxx_chipset); + return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]); } static struct pci_device_id via_pci_tbl[] = { { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, via_pci_tbl); diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/ide/setup-pci.c 2005-02-28 17:22:05 -08:00 @@ -579,7 +579,6 @@ int port; int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; - static int secondpdc = 0; u8 tmp; index->all = 0xf0f0; @@ -590,22 +589,10 @@ for (port = 0; port <= 1; ++port) { ide_pci_enablebit_t *e = &(d->enablebits[port]); - - /* - * If this is a Promise FakeRaid controller, - * the 2nd controller will be marked as - * disabled while it is actually there and enabled - * by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((d->flags & IDEPCI_FLAG_FORCE_PDC) && - (secondpdc++==1) && (port==1)) - goto controller_ok; - + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ -controller_ok: if (d->channels <= port) break; diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c 2005-02-28 17:22:05 -08:00 +++ b/drivers/scsi/ide-scsi.c 2005-02-28 17:22:05 -08:00 @@ -96,14 +96,42 @@ */ #define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_scsi_obj { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct Scsi_Host *host; + idescsi_pc_t *pc; /* Current packet command */ unsigned long flags; /* Status/Action flags */ unsigned long transform; /* SCSI cmd translation layer */ unsigned long log; /* log flags */ } idescsi_scsi_t; +static DECLARE_MUTEX(idescsi_ref_sem); + +#define ide_scsi_g(disk) \ + container_of((disk)->private_data, struct ide_scsi_obj, driver) + +static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) +{ + struct ide_scsi_obj *scsi = NULL; + + down(&idescsi_ref_sem); + scsi = ide_scsi_g(disk); + if (scsi) + scsi_host_get(scsi->host); + up(&idescsi_ref_sem); + return scsi; +} + +static void ide_scsi_put(struct ide_scsi_obj *scsi) +{ + down(&idescsi_ref_sem); + scsi_host_put(scsi->host); + up(&idescsi_ref_sem); +} + static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host) { return (idescsi_scsi_t*) (&host[1]); @@ -298,9 +326,12 @@ printk ("ide-scsi: %s: queue cmd = ", drive->name); hexdump(pc->c, 6); } + rq->rq_disk = scsi->disk; return ide_do_drive_cmd(drive, rq, ide_preempt); } +static int idescsi_end_request(ide_drive_t *, int, int); + static ide_startstop_t idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) { @@ -309,7 +340,9 @@ HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); rq->errors++; - DRIVER(drive)->end_request(drive, 0, 0); + + idescsi_end_request(drive, 0, 0); + return ide_stopped; } @@ -321,7 +354,9 @@ ((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number); #endif rq->errors |= ERROR_MAX; - DRIVER(drive)->end_request(drive, 0, 0); + + idescsi_end_request(drive, 0, 0); + return ide_stopped; } @@ -679,7 +714,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) { DRIVER(drive)->busy++; - drive->ready_stat = 0; if (drive->id && (drive->id->config & 0x0060) == 0x20) set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit(IDESCSI_TRANSFORM, &scsi->transform); @@ -694,21 +728,37 @@ static int idescsi_cleanup (ide_drive_t *drive) { struct Scsi_Host *scsihost = drive->driver_data; + struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); + struct gendisk *g = scsi->disk; if (ide_unregister_subdriver(drive)) return 1; - - /* FIXME?: Are these two statements necessary? */ + + ide_unregister_region(g); + + /* FIXME: drive->driver_data shouldn't be used */ drive->driver_data = NULL; - drive->disk->fops = ide_fops; + /* FIXME: add driver's private struct gendisk */ + g->private_data = NULL; + put_disk(g); scsi_remove_host(scsihost); - scsi_host_put(scsihost); + ide_scsi_put(scsi); + return 0; } static int idescsi_attach(ide_drive_t *drive); +#ifdef CONFIG_PROC_FS +static ide_proc_entry_t idescsi_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#else +# define idescsi_proc NULL +#endif + /* * IDE subdriver functions, registered with ide.c */ @@ -719,6 +769,7 @@ .media = ide_scsi, .busy = 0, .supports_dsc_overlap = 0, + .proc = idescsi_proc, .attach = idescsi_attach, .cleanup = idescsi_cleanup, .do_request = idescsi_do_request, @@ -730,15 +781,30 @@ static int idescsi_ide_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_scsi_obj *scsi; + ide_drive_t *drive; + + if (!(scsi = ide_scsi_get(disk))) + return -ENXIO; + + drive = scsi->drive; + drive->usage++; + return 0; } static int idescsi_ide_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_scsi_obj *scsi = ide_scsi_g(disk); + ide_drive_t *drive = scsi->drive; + drive->usage--; + + ide_scsi_put(scsi); + return 0; } @@ -746,7 +812,8 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - return generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk); + return generic_ide_ioctl(scsi->drive, file, bdev, cmd, arg); } static struct block_device_operations idescsi_ops = { @@ -858,6 +925,7 @@ rq->special = (char *) pc; rq->flags = REQ_SPECIAL; spin_unlock_irq(host->host_lock); + rq->rq_disk = scsi->disk; (void) ide_do_drive_cmd (drive, rq, ide_end); spin_lock_irq(host->host_lock); return 0; @@ -1033,8 +1101,9 @@ { idescsi_scsi_t *idescsi; struct Scsi_Host *host; + struct gendisk *g; static int warned; - int err; + int err = -ENOMEM; if (!warned && drive->media == ide_cdrom) { printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n"); @@ -1047,6 +1116,12 @@ !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return 1; + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_host_put; + + ide_init_disk(g, drive); + host->max_id = 1; #if IDESCSI_DEBUG_LOG @@ -1061,19 +1136,27 @@ drive->driver_data = host; idescsi = scsihost_to_idescsi(host); idescsi->drive = drive; + idescsi->driver = &idescsi_driver; + idescsi->host = host; + idescsi->disk = g; + g->private_data = &idescsi->driver; err = ide_register_subdriver(drive, &idescsi_driver); if (!err) { idescsi_setup (drive, idescsi); - drive->disk->fops = &idescsi_ops; + g->fops = &idescsi_ops; + ide_register_region(g); err = scsi_add_host(host, &drive->gendev); if (!err) { scsi_scan_host(host); return 0; } /* fall through on error */ + ide_unregister_region(g); ide_unregister_subdriver(drive); } + put_disk(g); +out_host_put: scsi_host_put(host); return err; } diff -Nru a/include/linux/ata.h b/include/linux/ata.h --- a/include/linux/ata.h 2005-02-28 17:22:05 -08:00 +++ b/include/linux/ata.h 2005-02-28 17:22:05 -08:00 @@ -174,6 +174,7 @@ ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ + ATA_TFLAG_IO_16BIT = (1 << 4), /* force 16bit pio */ }; enum ata_tf_protocols { diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h 2005-02-28 17:22:05 -08:00 +++ b/include/linux/ide.h 2005-02-28 17:22:05 -08:00 @@ -718,6 +718,7 @@ */ unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ + unsigned post_reset : 1; u8 quirk_list; /* considered quirky, set for a specific host */ u8 init_speed; /* transfer rate set at boot */ @@ -756,7 +757,6 @@ struct list_head list; struct device gendev; struct semaphore gendev_rel_sem; /* to deal with device release() */ - struct gendisk *disk; } ide_drive_t; #define IDE_CHIPSET_PCI_MASK \ @@ -1098,15 +1098,10 @@ ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); - void (*pre_reset)(ide_drive_t *); - sector_t (*capacity)(ide_drive_t *); - ide_startstop_t (*special)(ide_drive_t *); ide_proc_entry_t *proc; int (*attach)(ide_drive_t *); void (*ata_prebuilder)(ide_drive_t *); void (*atapi_prebuilder)(ide_drive_t *); - ide_startstop_t (*start_power_step)(ide_drive_t *, struct request *); - void (*complete_power_step)(ide_drive_t *, struct request *, u8, u8); struct device_driver gen_driver; struct list_head drives; struct list_head drivers; @@ -1114,7 +1109,7 @@ #define DRIVER(drive) ((drive)->driver) -extern int generic_ide_ioctl(struct file *, struct block_device *, unsigned, unsigned long); +int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); /* * ide_hwifs[] is the master data structure used to keep track @@ -1263,6 +1258,7 @@ * struct hd_drive_hob_hdr hobf; * hob_struct_t hobf; */ + unsigned long flags; /* ATA_TFLAG_xxx */ task_ioreg_t tfRegister[8]; task_ioreg_t hobRegister[8]; ide_reg_valid_t tf_out_flags; @@ -1331,7 +1327,7 @@ extern void do_ide_request(request_queue_t *); extern void ide_init_subdrivers(void); -extern struct block_device_operations ide_fops[]; +void ide_init_disk(struct gendisk *, ide_drive_t *); extern int ata_attach(ide_drive_t *); @@ -1375,7 +1371,6 @@ enum { /* Uses ISA control ports not PCI ones. */ IDEPCI_FLAG_ISA_PORTS = (1 << 0), - IDEPCI_FLAG_FORCE_PDC = (1 << 1), }; typedef struct ide_pci_device_s { @@ -1445,6 +1440,9 @@ extern int ide_hwif_request_regions(ide_hwif_t *hwif); extern void ide_hwif_release_regions(ide_hwif_t* hwif); extern void ide_unregister (unsigned int index); + +void ide_register_region(struct gendisk *); +void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_hwif_t *); diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h 2005-02-28 17:22:05 -08:00 +++ b/include/linux/pci_ids.h 2005-02-28 17:22:05 -08:00 @@ -1280,6 +1280,7 @@ #define PCI_DEVICE_ID_VIA_8703_51_0 0x3148 #define PCI_DEVICE_ID_VIA_8237_SATA 0x3149 #define PCI_DEVICE_ID_VIA_XN266 0x3156 +#define PCI_DEVICE_ID_VIA_6410 0x3164 #define PCI_DEVICE_ID_VIA_8754C_0 0x3168 #define PCI_DEVICE_ID_VIA_8235 0x3177 #define PCI_DEVICE_ID_VIA_P4N333 0x3178