Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (66 commits) ata: Add documentation for hard disk shock protection interface (v3) ide: Implement disk shock protection support (v4) ide-cd: fix printk format warning piix: add Hercules EC-900 mini-notebook to ich_laptop short cable list ide-atapi: assign taskfile flags per device type ide-cd: move cdrom_info.dma to ide_drive_t.dma ide: add ide_drive_t.dma flag ide-cd: add a debug_mask module parameter ide-cd: convert driver to new ide debugging macro (v3) ide: move SFF DMA code to ide-dma-sff.c ide: cleanup ide-dma.c ide: cleanup ide_build_dmatable() ide: remove needless includes from ide-dma.c ide: switch to DMA-mapping API part #2 ide: make ide_dma_timeout() available also for CONFIG_BLK_DEV_IDEDMA_SFF=n ide: make ide_dma_lost_irq() available also for CONFIG_BLK_DEV_IDEDMA_SFF=n ide: __ide_dma_end() -> ide_dma_end() pmac: remove needless pmac_ide_destroy_dmatable() wrapper pmac: remove superfluous pmif == NULL checks ide: Two fixes regarding memory allocation ...
This commit is contained in:
commit
7591103c08
149
Documentation/laptops/disk-shock-protection.txt
Normal file
149
Documentation/laptops/disk-shock-protection.txt
Normal file
@ -0,0 +1,149 @@
|
||||
Hard disk shock protection
|
||||
==========================
|
||||
|
||||
Author: Elias Oltmanns <eo@nebensachen.de>
|
||||
Last modified: 2008-10-03
|
||||
|
||||
|
||||
0. Contents
|
||||
-----------
|
||||
|
||||
1. Intro
|
||||
2. The interface
|
||||
3. References
|
||||
4. CREDITS
|
||||
|
||||
|
||||
1. Intro
|
||||
--------
|
||||
|
||||
ATA/ATAPI-7 specifies the IDLE IMMEDIATE command with unload feature.
|
||||
Issuing this command should cause the drive to switch to idle mode and
|
||||
unload disk heads. This feature is being used in modern laptops in
|
||||
conjunction with accelerometers and appropriate software to implement
|
||||
a shock protection facility. The idea is to stop all I/O operations on
|
||||
the internal hard drive and park its heads on the ramp when critical
|
||||
situations are anticipated. The desire to have such a feature
|
||||
available on GNU/Linux systems has been the original motivation to
|
||||
implement a generic disk head parking interface in the Linux kernel.
|
||||
Please note, however, that other components have to be set up on your
|
||||
system in order to get disk shock protection working (see
|
||||
section 3. References below for pointers to more information about
|
||||
that).
|
||||
|
||||
|
||||
2. The interface
|
||||
----------------
|
||||
|
||||
For each ATA device, the kernel exports the file
|
||||
block/*/device/unload_heads in sysfs (here assumed to be mounted under
|
||||
/sys). Access to /sys/block/*/device/unload_heads is denied with
|
||||
-EOPNOTSUPP if the device does not support the unload feature.
|
||||
Otherwise, writing an integer value to this file will take the heads
|
||||
of the respective drive off the platter and block all I/O operations
|
||||
for the specified number of milliseconds. When the timeout expires and
|
||||
no further disk head park request has been issued in the meantime,
|
||||
normal operation will be resumed. The maximal value accepted for a
|
||||
timeout is 30000 milliseconds. Exceeding this limit will return
|
||||
-EOVERFLOW, but heads will be parked anyway and the timeout will be
|
||||
set to 30 seconds. However, you can always change a timeout to any
|
||||
value between 0 and 30000 by issuing a subsequent head park request
|
||||
before the timeout of the previous one has expired. In particular, the
|
||||
total timeout can exceed 30 seconds and, more importantly, you can
|
||||
cancel a previously set timeout and resume normal operation
|
||||
immediately by specifying a timeout of 0. Values below -2 are rejected
|
||||
with -EINVAL (see below for the special meaning of -1 and -2). If the
|
||||
timeout specified for a recent head park request has not yet expired,
|
||||
reading from /sys/block/*/device/unload_heads will report the number
|
||||
of milliseconds remaining until normal operation will be resumed;
|
||||
otherwise, reading the unload_heads attribute will return 0.
|
||||
|
||||
For example, do the following in order to park the heads of drive
|
||||
/dev/sda and stop all I/O operations for five seconds:
|
||||
|
||||
# echo 5000 > /sys/block/sda/device/unload_heads
|
||||
|
||||
A simple
|
||||
|
||||
# cat /sys/block/sda/device/unload_heads
|
||||
|
||||
will show you how many milliseconds are left before normal operation
|
||||
will be resumed.
|
||||
|
||||
A word of caution: The fact that the interface operates on a basis of
|
||||
milliseconds may raise expectations that cannot be satisfied in
|
||||
reality. In fact, the ATA specs clearly state that the time for an
|
||||
unload operation to complete is vendor specific. The hint in ATA-7
|
||||
that this will typically be within 500 milliseconds apparently has
|
||||
been dropped in ATA-8.
|
||||
|
||||
There is a technical detail of this implementation that may cause some
|
||||
confusion and should be discussed here. When a head park request has
|
||||
been issued to a device successfully, all I/O operations on the
|
||||
controller port this device is attached to will be deferred. That is
|
||||
to say, any other device that may be connected to the same port will
|
||||
be affected too. The only exception is that a subsequent head unload
|
||||
request to that other device will be executed immediately. Further
|
||||
operations on that port will be deferred until the timeout specified
|
||||
for either device on the port has expired. As far as PATA (old style
|
||||
IDE) configurations are concerned, there can only be two devices
|
||||
attached to any single port. In SATA world we have port multipliers
|
||||
which means that a user-issued head parking request to one device may
|
||||
actually result in stopping I/O to a whole bunch of devices. However,
|
||||
since this feature is supposed to be used on laptops and does not seem
|
||||
to be very useful in any other environment, there will be mostly one
|
||||
device per port. Even if the CD/DVD writer happens to be connected to
|
||||
the same port as the hard drive, it generally *should* recover just
|
||||
fine from the occasional buffer under-run incurred by a head park
|
||||
request to the HD. Actually, when you are using an ide driver rather
|
||||
than its libata counterpart (i.e. your disk is called /dev/hda
|
||||
instead of /dev/sda), then parking the heads of one drive (drive X)
|
||||
will generally not affect the mode of operation of another drive
|
||||
(drive Y) on the same port as described above. It is only when a port
|
||||
reset is required to recover from an exception on drive Y that further
|
||||
I/O operations on that drive (and the reset itself) will be delayed
|
||||
until drive X is no longer in the parked state.
|
||||
|
||||
Finally, there are some hard drives that only comply with an earlier
|
||||
version of the ATA standard than ATA-7, but do support the unload
|
||||
feature nonetheless. Unfortunately, there is no safe way Linux can
|
||||
detect these devices, so you won't be able to write to the
|
||||
unload_heads attribute. If you know that your device really does
|
||||
support the unload feature (for instance, because the vendor of your
|
||||
laptop or the hard drive itself told you so), then you can tell the
|
||||
kernel to enable the usage of this feature for that drive by writing
|
||||
the special value -1 to the unload_heads attribute:
|
||||
|
||||
# echo -1 > /sys/block/sda/device/unload_heads
|
||||
|
||||
will enable the feature for /dev/sda, and giving -2 instead of -1 will
|
||||
disable it again.
|
||||
|
||||
|
||||
3. References
|
||||
-------------
|
||||
|
||||
There are several laptops from different vendors featuring shock
|
||||
protection capabilities. As manufacturers have refused to support open
|
||||
source development of the required software components so far, Linux
|
||||
support for shock protection varies considerably between different
|
||||
hardware implementations. Ideally, this section should contain a list
|
||||
of pointers at different projects aiming at an implementation of shock
|
||||
protection on different systems. Unfortunately, I only know of a
|
||||
single project which, although still considered experimental, is fit
|
||||
for use. Please feel free to add projects that have been the victims
|
||||
of my ignorance.
|
||||
|
||||
- http://www.thinkwiki.org/wiki/HDAPS
|
||||
See this page for information about Linux support of the hard disk
|
||||
active protection system as implemented in IBM/Lenovo Thinkpads.
|
||||
|
||||
|
||||
4. CREDITS
|
||||
----------
|
||||
|
||||
This implementation of disk head parking has been inspired by a patch
|
||||
originally published by Jon Escombe <lists@dresco.co.uk>. My efforts
|
||||
to develop an implementation of this feature that is fit to be merged
|
||||
into mainline have been aided by various kernel developers, in
|
||||
particular by Tejun Heo and Bartlomiej Zolnierkiewicz.
|
@ -19,35 +19,6 @@
|
||||
#include <linux/stddef.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
static __inline__ int ide_probe_legacy(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev *dev;
|
||||
/*
|
||||
* This can be called on the ide_setup() path, super-early in
|
||||
* boot. But the down_read() will enable local interrupts,
|
||||
* which can cause some machines to crash. So here we detect
|
||||
* and flag that situation and bail out early.
|
||||
*/
|
||||
if (no_pci_devices())
|
||||
return 0;
|
||||
dev = pci_get_class(PCI_CLASS_BRIDGE_EISA << 8, NULL);
|
||||
if (dev)
|
||||
goto found;
|
||||
dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
|
||||
if (dev)
|
||||
goto found;
|
||||
return 0;
|
||||
found:
|
||||
pci_dev_put(dev);
|
||||
return 1;
|
||||
#elif defined(CONFIG_EISA) || defined(CONFIG_ISA)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* MIPS port and memory-mapped I/O string operations. */
|
||||
static inline void __ide_flush_prologue(void)
|
||||
{
|
||||
|
@ -53,11 +53,6 @@ extern struct fd_ops no_fd_ops;
|
||||
struct fd_ops *fd_ops;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
|
||||
extern struct ide_ops no_ide_ops;
|
||||
struct ide_ops *ide_ops;
|
||||
#endif
|
||||
|
||||
extern struct rtc_ops no_rtc_ops;
|
||||
struct rtc_ops *rtc_ops;
|
||||
|
||||
|
@ -54,38 +54,6 @@ menuconfig IDE
|
||||
|
||||
if IDE
|
||||
|
||||
config BLK_DEV_IDE
|
||||
tristate "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
|
||||
---help---
|
||||
If you say Y here, you will use the full-featured IDE driver to
|
||||
control up to ten ATA/IDE interfaces, each being able to serve a
|
||||
"master" and a "slave" device, for a total of up to twenty ATA/IDE
|
||||
disk/cdrom/tape/floppy drives.
|
||||
|
||||
Useful information about large (>540 MB) IDE disks, multiple
|
||||
interfaces, what to do if ATA/IDE devices are not automatically
|
||||
detected, sound card ATA/IDE ports, module support, and other
|
||||
topics, is contained in <file:Documentation/ide/ide.txt>. For detailed
|
||||
information about hard drives, consult the Disk-HOWTO and the
|
||||
Multi-Disk-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To fine-tune ATA/IDE drive/interface parameters for improved
|
||||
performance, look for the hdparm package at
|
||||
<ftp://ibiblio.org/pub/Linux/system/hardware/>.
|
||||
|
||||
To compile this driver as a module, choose M here and read
|
||||
<file:Documentation/ide/ide.txt>. The module will be called ide-mod.
|
||||
Do not compile this driver as a module if your root file system (the
|
||||
one containing the directory /) is located on an IDE device.
|
||||
|
||||
If you have one or more IDE drives, say Y or M here. If your system
|
||||
has no IDE drives, or if memory requirements are really tight, you
|
||||
could say N here, and select the "Old hard disk driver" below
|
||||
instead to save about 13 KB of memory in the kernel.
|
||||
|
||||
if BLK_DEV_IDE
|
||||
|
||||
comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
|
||||
|
||||
config IDE_TIMINGS
|
||||
@ -348,7 +316,7 @@ config BLK_DEV_IDEPCI
|
||||
|
||||
config IDEPCI_PCIBUS_ORDER
|
||||
bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
|
||||
depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
|
||||
depends on IDE=y && BLK_DEV_IDEPCI
|
||||
default y
|
||||
help
|
||||
Probe IDE PCI devices in the order in which they appear on the
|
||||
@ -729,7 +697,7 @@ endif
|
||||
|
||||
config BLK_DEV_IDE_PMAC
|
||||
tristate "PowerMac on-board IDE support"
|
||||
depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
|
||||
depends on PPC_PMAC && IDE=y
|
||||
select IDE_TIMINGS
|
||||
help
|
||||
This driver provides support for the on-board IDE controller on
|
||||
@ -963,6 +931,4 @@ config BLK_DEV_IDEDMA
|
||||
def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
|
||||
BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
|
||||
|
||||
endif
|
||||
|
||||
endif # IDE
|
||||
|
@ -5,24 +5,25 @@
|
||||
EXTRA_CFLAGS += -Idrivers/ide
|
||||
|
||||
ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
|
||||
ide-taskfile.o ide-pio-blacklist.o
|
||||
ide-taskfile.o ide-park.o ide-pio-blacklist.o
|
||||
|
||||
# core IDE code
|
||||
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
|
||||
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
|
||||
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
|
||||
obj-$(CONFIG_IDE) += ide-core.o
|
||||
|
||||
ifeq ($(CONFIG_IDE_ARM), y)
|
||||
ide-arm-core-y += arm/ide_arm.o
|
||||
obj-y += ide-arm-core.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/
|
||||
obj-$(CONFIG_IDE) += legacy/ pci/
|
||||
|
||||
obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
|
||||
|
||||
@ -31,15 +32,21 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
|
||||
obj-y += cmd640-core.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDE) += ppc/
|
||||
obj-$(CONFIG_IDE) += ppc/
|
||||
obj-$(CONFIG_IDE_H8300) += h8300/
|
||||
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
|
||||
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
|
||||
|
||||
ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o
|
||||
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
|
||||
ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
|
||||
ifeq ($(CONFIG_IDE_PROC_FS), y)
|
||||
ide-disk_mod-y += ide-disk_proc.o
|
||||
ide-floppy_mod-y += ide-floppy_proc.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o
|
||||
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
|
||||
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o
|
||||
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
|
||||
@ -54,4 +61,4 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
|
||||
obj-y += ide-platform-core.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/
|
||||
obj-$(CONFIG_IDE) += arm/ mips/
|
||||
|
@ -372,25 +372,6 @@ static int icside_dma_test_irq(ide_drive_t *drive)
|
||||
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
|
||||
}
|
||||
|
||||
static void icside_dma_timeout(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
|
||||
|
||||
if (icside_dma_test_irq(drive))
|
||||
return;
|
||||
|
||||
ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
|
||||
|
||||
icside_dma_end(drive);
|
||||
}
|
||||
|
||||
static void icside_dma_lost_irq(ide_drive_t *drive)
|
||||
{
|
||||
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
|
||||
}
|
||||
|
||||
static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
|
||||
{
|
||||
hwif->dmatable_cpu = NULL;
|
||||
@ -406,8 +387,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = {
|
||||
.dma_start = icside_dma_start,
|
||||
.dma_end = icside_dma_end,
|
||||
.dma_test_irq = icside_dma_test_irq,
|
||||
.dma_timeout = icside_dma_timeout,
|
||||
.dma_lost_irq = icside_dma_lost_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
};
|
||||
#else
|
||||
#define icside_v6_dma_ops NULL
|
||||
|
@ -80,7 +80,7 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
|
||||
outb(tf->lbah, io_ports->lbah_addr);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
|
||||
outb((tf->device & HIHI) | drive->select.all,
|
||||
outb((tf->device & HIHI) | drive->select,
|
||||
io_ports->device_addr);
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
|
||||
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
|
||||
hwif->name, dev->bus_id, port, hwif->channel);
|
||||
|
||||
if (!drive->present) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
|
||||
DEBPRINT("%s drive %d:%d not present\n",
|
||||
hwif->name, hwif->channel, port);
|
||||
goto out;
|
||||
@ -420,8 +420,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
|
||||
|
||||
DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
|
||||
|
||||
if (!drive->present)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
goto out;
|
||||
|
||||
if (!gtf_count) /* shouldn't be here */
|
||||
goto out;
|
||||
|
||||
@ -660,7 +661,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
|
||||
if (!drive->acpidata->obj_handle)
|
||||
drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
|
||||
|
||||
if (drive->acpidata->obj_handle && drive->present) {
|
||||
if (drive->acpidata->obj_handle &&
|
||||
(drive->dev_flags & IDE_DFLAG_PRESENT)) {
|
||||
acpi_bus_set_power(drive->acpidata->obj_handle,
|
||||
on? ACPI_STATE_D0: ACPI_STATE_D3);
|
||||
}
|
||||
@ -720,7 +722,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
|
||||
|
||||
memset(drive->acpidata, 0, sizeof(*drive->acpidata));
|
||||
|
||||
if (!drive->present)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
continue;
|
||||
|
||||
err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
|
||||
@ -745,7 +747,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
|
||||
for (i = 0; i < MAX_DRIVES; i++) {
|
||||
drive = &hwif->drives[i];
|
||||
|
||||
if (drive->present)
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT)
|
||||
/* Execute ACPI startup code */
|
||||
ide_acpi_exec_tfs(drive);
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ EXPORT_SYMBOL_GPL(ide_init_pc);
|
||||
* the current request, so that it will be processed immediately, on the next
|
||||
* pass through the driver.
|
||||
*/
|
||||
void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
|
||||
struct ide_atapi_pc *pc, struct request *rq)
|
||||
static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
|
||||
struct ide_atapi_pc *pc, struct request *rq)
|
||||
{
|
||||
blk_rq_init(NULL, rq);
|
||||
rq->cmd_type = REQ_TYPE_SPECIAL;
|
||||
@ -137,7 +137,6 @@ void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
|
||||
rq->cmd[13] = REQ_IDETAPE_PC1;
|
||||
ide_do_drive_cmd(drive, rq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_queue_pc_head);
|
||||
|
||||
/*
|
||||
* Add a special packet command request to the tail of the request queue,
|
||||
@ -203,25 +202,80 @@ int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_set_media_lock);
|
||||
|
||||
/* TODO: unify the code thus making some arguments go away */
|
||||
ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
|
||||
void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
|
||||
void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
|
||||
int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
|
||||
void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
|
||||
{
|
||||
ide_init_pc(pc);
|
||||
pc->c[0] = REQUEST_SENSE;
|
||||
if (drive->media == ide_floppy) {
|
||||
pc->c[4] = 255;
|
||||
pc->req_xfer = 18;
|
||||
} else {
|
||||
pc->c[4] = 20;
|
||||
pc->req_xfer = 20;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
|
||||
|
||||
/*
|
||||
* Called when an error was detected during the last packet command.
|
||||
* We queue a request sense packet command in the head of the request list.
|
||||
*/
|
||||
void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
|
||||
{
|
||||
struct request *rq = &drive->request_sense_rq;
|
||||
struct ide_atapi_pc *pc = &drive->request_sense_pc;
|
||||
|
||||
(void)ide_read_error(drive);
|
||||
ide_create_request_sense_cmd(drive, pc);
|
||||
if (drive->media == ide_tape)
|
||||
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
|
||||
ide_queue_pc_head(drive, disk, pc, rq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_retry_pc);
|
||||
|
||||
int ide_scsi_expiry(ide_drive_t *drive)
|
||||
{
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
|
||||
debug_log("%s called for %lu at %lu\n", __func__,
|
||||
pc->scsi_cmd->serial_number, jiffies);
|
||||
|
||||
pc->flags |= PC_FLAG_TIMEDOUT;
|
||||
|
||||
return 0; /* we do not want the IDE subsystem to retry */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_scsi_expiry);
|
||||
|
||||
/*
|
||||
* This is the usual interrupt handler which will be called during a packet
|
||||
* command. We will transfer some of the data (as requested by the drive)
|
||||
* and will re-point interrupt handler to us.
|
||||
*/
|
||||
static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
||||
{
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
|
||||
xfer_func_t *xferfunc;
|
||||
unsigned int temp;
|
||||
ide_expiry_t *expiry;
|
||||
unsigned int timeout, temp;
|
||||
u16 bcount;
|
||||
u8 stat, ireason, scsi = drive->scsi;
|
||||
u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
|
||||
|
||||
debug_log("Enter %s - interrupt handler\n", __func__);
|
||||
|
||||
if (scsi) {
|
||||
timeout = ide_scsi_get_timeout(pc);
|
||||
expiry = ide_scsi_expiry;
|
||||
} else {
|
||||
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
|
||||
: WAIT_TAPE_CMD;
|
||||
expiry = NULL;
|
||||
}
|
||||
|
||||
if (pc->flags & PC_FLAG_TIMEDOUT) {
|
||||
drive->pc_callback(drive);
|
||||
drive->pc_callback(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
@ -238,8 +292,8 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
pc->flags |= PC_FLAG_DMA_ERROR;
|
||||
} else {
|
||||
pc->xferred = pc->req_xfer;
|
||||
if (update_buffers)
|
||||
update_buffers(drive, pc);
|
||||
if (drive->pc_update_buffers)
|
||||
drive->pc_update_buffers(drive, pc);
|
||||
}
|
||||
debug_log("%s: DMA finished\n", drive->name);
|
||||
}
|
||||
@ -276,21 +330,19 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
|
||||
|
||||
/* Retry operation */
|
||||
retry_pc(drive);
|
||||
ide_retry_pc(drive, rq->rq_disk);
|
||||
|
||||
/* queued, but not started */
|
||||
return ide_stopped;
|
||||
}
|
||||
cmd_finished:
|
||||
pc->error = 0;
|
||||
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
|
||||
(stat & ATA_DSC) == 0) {
|
||||
dsc_handle(drive);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
|
||||
dsc = 1;
|
||||
|
||||
/* Command finished - Call the callback function */
|
||||
drive->pc_callback(drive);
|
||||
drive->pc_callback(drive, dsc);
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -336,7 +388,8 @@ cmd_finished:
|
||||
temp = 0;
|
||||
if (temp) {
|
||||
if (pc->sg)
|
||||
io_buffers(drive, pc, temp, 0);
|
||||
drive->pc_io_buffers(drive, pc,
|
||||
temp, 0);
|
||||
else
|
||||
tp_ops->input_data(drive, NULL,
|
||||
pc->cur_pos, temp);
|
||||
@ -348,9 +401,7 @@ cmd_finished:
|
||||
pc->xferred += temp;
|
||||
pc->cur_pos += temp;
|
||||
ide_pad_transfer(drive, 0, bcount - temp);
|
||||
ide_set_handler(drive, handler, timeout,
|
||||
expiry);
|
||||
return ide_started;
|
||||
goto next_irq;
|
||||
}
|
||||
debug_log("The device wants to send us more data than "
|
||||
"expected - allowing transfer\n");
|
||||
@ -362,7 +413,7 @@ cmd_finished:
|
||||
if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
|
||||
(drive->media == ide_tape && !scsi && pc->bh) ||
|
||||
(scsi && pc->sg)) {
|
||||
int done = io_buffers(drive, pc, bcount,
|
||||
int done = drive->pc_io_buffers(drive, pc, bcount,
|
||||
!!(pc->flags & PC_FLAG_WRITING));
|
||||
|
||||
/* FIXME: don't do partial completions */
|
||||
@ -377,12 +428,11 @@ cmd_finished:
|
||||
|
||||
debug_log("[cmd %x] transferred %d bytes on that intr.\n",
|
||||
rq->cmd[0], bcount);
|
||||
|
||||
next_irq:
|
||||
/* And set the interrupt handler again */
|
||||
ide_set_handler(drive, handler, timeout, expiry);
|
||||
ide_set_handler(drive, ide_pc_intr, timeout, expiry);
|
||||
return ide_started;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_pc_intr);
|
||||
|
||||
static u8 ide_read_ireason(ide_drive_t *drive)
|
||||
{
|
||||
@ -418,12 +468,22 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
|
||||
return ireason;
|
||||
}
|
||||
|
||||
ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
ide_handler_t *handler, unsigned int timeout,
|
||||
ide_expiry_t *expiry)
|
||||
static int ide_delayed_transfer_pc(ide_drive_t *drive)
|
||||
{
|
||||
/* Send the actual packet */
|
||||
drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
|
||||
|
||||
/* Timeout for the packet command */
|
||||
return WAIT_FLOPPY_CMD;
|
||||
}
|
||||
|
||||
static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
|
||||
{
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
ide_expiry_t *expiry;
|
||||
unsigned int timeout;
|
||||
ide_startstop_t startstop;
|
||||
u8 ireason;
|
||||
|
||||
@ -434,7 +494,8 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
}
|
||||
|
||||
ireason = ide_read_ireason(drive);
|
||||
if (drive->media == ide_tape && !drive->scsi)
|
||||
if (drive->media == ide_tape &&
|
||||
(drive->dev_flags & IDE_DFLAG_SCSI) == 0)
|
||||
ireason = ide_wait_ireason(drive, ireason);
|
||||
|
||||
if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
|
||||
@ -443,8 +504,27 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
|
||||
/*
|
||||
* If necessary schedule the packet transfer to occur 'timeout'
|
||||
* miliseconds later in ide_delayed_transfer_pc() after the device
|
||||
* says it's ready for a packet.
|
||||
*/
|
||||
if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
|
||||
timeout = drive->pc_delay;
|
||||
expiry = &ide_delayed_transfer_pc;
|
||||
} else {
|
||||
if (drive->dev_flags & IDE_DFLAG_SCSI) {
|
||||
timeout = ide_scsi_get_timeout(pc);
|
||||
expiry = ide_scsi_expiry;
|
||||
} else {
|
||||
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
|
||||
: WAIT_TAPE_CMD;
|
||||
expiry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the interrupt routine */
|
||||
ide_set_handler(drive, handler, timeout, expiry);
|
||||
ide_set_handler(drive, ide_pc_intr, timeout, expiry);
|
||||
|
||||
/* Begin DMA, if necessary */
|
||||
if (pc->flags & PC_FLAG_DMA_OK) {
|
||||
@ -458,22 +538,22 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
|
||||
return ide_started;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_transfer_pc);
|
||||
|
||||
ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
ide_handler_t *handler, unsigned int timeout,
|
||||
ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
|
||||
ide_expiry_t *expiry)
|
||||
{
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u32 tf_flags;
|
||||
u16 bcount;
|
||||
u8 dma = 0;
|
||||
u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
|
||||
|
||||
/* We haven't transferred any data yet */
|
||||
pc->xferred = 0;
|
||||
pc->cur_pos = pc->buf;
|
||||
|
||||
/* Request to transfer the entire buffer at once */
|
||||
if (drive->media == ide_tape && !drive->scsi)
|
||||
if (drive->media == ide_tape && scsi == 0)
|
||||
bcount = pc->req_xfer;
|
||||
else
|
||||
bcount = min(pc->req_xfer, 63 * 1024);
|
||||
@ -483,28 +563,35 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
ide_dma_off(drive);
|
||||
}
|
||||
|
||||
if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
|
||||
if (drive->scsi)
|
||||
if ((pc->flags & PC_FLAG_DMA_OK) &&
|
||||
(drive->dev_flags & IDE_DFLAG_USING_DMA)) {
|
||||
if (scsi)
|
||||
hwif->sg_mapped = 1;
|
||||
dma = !hwif->dma_ops->dma_setup(drive);
|
||||
if (drive->scsi)
|
||||
drive->dma = !hwif->dma_ops->dma_setup(drive);
|
||||
if (scsi)
|
||||
hwif->sg_mapped = 0;
|
||||
}
|
||||
|
||||
if (!dma)
|
||||
if (!drive->dma)
|
||||
pc->flags &= ~PC_FLAG_DMA_OK;
|
||||
|
||||
ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE,
|
||||
bcount, dma);
|
||||
if (scsi)
|
||||
tf_flags = 0;
|
||||
else if (drive->media == ide_cdrom || drive->media == ide_optical)
|
||||
tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
|
||||
else
|
||||
tf_flags = IDE_TFLAG_OUT_DEVICE;
|
||||
|
||||
ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
|
||||
|
||||
/* Issue the packet command */
|
||||
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
|
||||
ide_execute_command(drive, ATA_CMD_PACKET, handler,
|
||||
ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
|
||||
timeout, NULL);
|
||||
return ide_started;
|
||||
} else {
|
||||
ide_execute_pkt_cmd(drive);
|
||||
return (*handler)(drive);
|
||||
return ide_transfer_pc(drive);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_issue_pc);
|
||||
|
@ -23,6 +23,9 @@
|
||||
* Documentation/ide/ChangeLog.ide-cd.1994-2004
|
||||
*/
|
||||
|
||||
#define DRV_NAME "ide-cd"
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
#define IDECD_VERSION "5.00"
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -50,13 +53,16 @@
|
||||
|
||||
#include "ide-cd.h"
|
||||
|
||||
#define IDECD_DEBUG_LOG 1
|
||||
|
||||
#if IDECD_DEBUG_LOG
|
||||
#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
|
||||
#else
|
||||
#define ide_debug_log(lvl, fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(idecd_ref_mutex);
|
||||
|
||||
#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 void ide_cd_release(struct kref *);
|
||||
|
||||
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
|
||||
@ -64,7 +70,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk)
|
||||
struct cdrom_info *cd = NULL;
|
||||
|
||||
mutex_lock(&idecd_ref_mutex);
|
||||
cd = ide_cd_g(disk);
|
||||
cd = ide_drv_g(disk, cdrom_info);
|
||||
if (cd) {
|
||||
if (ide_device_get(cd->drive))
|
||||
cd = NULL;
|
||||
@ -102,6 +108,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
|
||||
{
|
||||
int log = 0;
|
||||
|
||||
ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
|
||||
sense->sense_key);
|
||||
|
||||
if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
|
||||
return 0;
|
||||
|
||||
@ -150,6 +159,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
|
||||
unsigned long bio_sectors;
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
|
||||
ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
|
||||
"sense_key: 0x%x\n", __func__, sense->error_code,
|
||||
sense->sense_key);
|
||||
|
||||
if (failed_command)
|
||||
ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
|
||||
__func__, failed_command->cmd[0]);
|
||||
|
||||
if (!cdrom_log_sense(drive, failed_command, sense))
|
||||
return;
|
||||
|
||||
@ -200,6 +217,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
struct request *rq = &info->request_sense_request;
|
||||
|
||||
ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);
|
||||
|
||||
if (sense == NULL)
|
||||
sense = &info->sense_data;
|
||||
|
||||
@ -219,6 +238,10 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
|
||||
/* NOTE! Save the failed command in "rq->buffer" */
|
||||
rq->buffer = (void *) failed_command;
|
||||
|
||||
if (failed_command)
|
||||
ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
|
||||
failed_command->cmd[0]);
|
||||
|
||||
ide_do_drive_cmd(drive, rq);
|
||||
}
|
||||
|
||||
@ -227,6 +250,10 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
int nsectors = rq->hard_cur_sectors;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
|
||||
"nsectors: %d\n", __func__, rq->cmd[0], uptodate,
|
||||
nsectors);
|
||||
|
||||
if (blk_sense_request(rq) && uptodate) {
|
||||
/*
|
||||
* For REQ_TYPE_SENSE, "rq->buffer" points to the original
|
||||
@ -269,6 +296,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
|
||||
if (!nsectors)
|
||||
nsectors = 1;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
|
||||
__func__, uptodate, nsectors);
|
||||
|
||||
ide_end_request(drive, uptodate, nsectors);
|
||||
}
|
||||
|
||||
@ -304,11 +334,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
sense_key = err >> 4;
|
||||
|
||||
if (rq == NULL) {
|
||||
printk(KERN_ERR "%s: missing rq in %s\n",
|
||||
printk(KERN_ERR PFX "%s: missing rq in %s\n",
|
||||
drive->name, __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
|
||||
"rq->cmd_type: 0x%x, err: 0x%x\n", __func__, stat,
|
||||
good_stat, rq->cmd_type, err);
|
||||
|
||||
if (blk_sense_request(rq)) {
|
||||
/*
|
||||
* We got an error trying to get sense info from the drive
|
||||
@ -374,7 +408,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
cdrom_saw_media_change(drive);
|
||||
|
||||
/* fail the request */
|
||||
printk(KERN_ERR "%s: tray open\n", drive->name);
|
||||
printk(KERN_ERR PFX "%s: tray open\n",
|
||||
drive->name);
|
||||
do_end_request = 1;
|
||||
} else {
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
@ -460,7 +495,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
if (stat & ATA_ERR)
|
||||
cdrom_queue_request_sense(drive, NULL, NULL);
|
||||
} else {
|
||||
blk_dump_rq_flags(rq, "ide-cd: bad rq");
|
||||
blk_dump_rq_flags(rq, PFX "bad rq");
|
||||
cdrom_end_request(drive, 0);
|
||||
}
|
||||
|
||||
@ -488,6 +523,9 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
unsigned long wait = 0;
|
||||
|
||||
ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
|
||||
rq->cmd[0]);
|
||||
|
||||
/*
|
||||
* Some commands are *slow* and normally take a long time to complete.
|
||||
* Usually we can use the ATAPI "disconnect" to bypass this, but not all
|
||||
@ -504,7 +542,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
|
||||
break;
|
||||
default:
|
||||
if (!(rq->cmd_flags & REQ_QUIET))
|
||||
printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n",
|
||||
printk(KERN_INFO PFX "cmd 0x%x timed out\n",
|
||||
rq->cmd[0]);
|
||||
wait = 0;
|
||||
break;
|
||||
@ -524,20 +562,21 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
|
||||
int xferlen,
|
||||
ide_handler_t *handler)
|
||||
{
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
|
||||
|
||||
/* FIXME: for Virtual DMA we must check harder */
|
||||
if (info->dma)
|
||||
info->dma = !hwif->dma_ops->dma_setup(drive);
|
||||
if (drive->dma)
|
||||
drive->dma = !hwif->dma_ops->dma_setup(drive);
|
||||
|
||||
/* set up the controller registers */
|
||||
ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
|
||||
xferlen, info->dma);
|
||||
xferlen, drive->dma);
|
||||
|
||||
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
|
||||
/* waiting for CDB interrupt, not DMA yet. */
|
||||
if (info->dma)
|
||||
if (drive->dma)
|
||||
drive->waiting_for_dma = 0;
|
||||
|
||||
/* packet command */
|
||||
@ -564,9 +603,10 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int cmd_len;
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
ide_startstop_t startstop;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
|
||||
|
||||
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
|
||||
/*
|
||||
* Here we should have been called after receiving an interrupt
|
||||
@ -578,7 +618,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
|
||||
return ide_stopped;
|
||||
|
||||
/* ok, next interrupt will be DMA interrupt */
|
||||
if (info->dma)
|
||||
if (drive->dma)
|
||||
drive->waiting_for_dma = 1;
|
||||
} else {
|
||||
/* otherwise, we must wait for DRQ to get set */
|
||||
@ -599,7 +639,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
|
||||
hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
|
||||
|
||||
/* start the DMA if need be */
|
||||
if (info->dma)
|
||||
if (drive->dma)
|
||||
hwif->dma_ops->dma_start(drive);
|
||||
|
||||
return ide_started;
|
||||
@ -615,6 +655,9 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
|
||||
__func__, ireason, rw);
|
||||
|
||||
/*
|
||||
* ireason == 0: the drive wants to receive data from us
|
||||
* ireason == 2: the drive is expecting to transfer data to us
|
||||
@ -624,7 +667,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
|
||||
else if (ireason == (rw << 1)) {
|
||||
|
||||
/* whoops... */
|
||||
printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
|
||||
printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
|
||||
drive->name, __func__);
|
||||
|
||||
ide_pad_transfer(drive, rw, len);
|
||||
@ -637,7 +680,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
|
||||
return 0;
|
||||
} else {
|
||||
/* drive wants a command packet, or invalid ireason... */
|
||||
printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
|
||||
printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
|
||||
drive->name, __func__, ireason);
|
||||
}
|
||||
|
||||
@ -654,17 +697,19 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
|
||||
*/
|
||||
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
|
||||
{
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);
|
||||
|
||||
if ((len % SECTOR_SIZE) == 0)
|
||||
return 0;
|
||||
|
||||
printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
|
||||
drive->name, __func__, len);
|
||||
printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
|
||||
__func__, len);
|
||||
|
||||
if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
|
||||
printk(KERN_ERR " This drive is not supported by "
|
||||
"this version of the driver\n");
|
||||
printk(KERN_ERR PFX "This drive is not supported by this "
|
||||
"version of the driver\n");
|
||||
else {
|
||||
printk(KERN_ERR " Trying to limit transfer sizes\n");
|
||||
printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
|
||||
drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
|
||||
}
|
||||
|
||||
@ -676,6 +721,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
|
||||
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
|
||||
struct request *rq)
|
||||
{
|
||||
ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
|
||||
rq->cmd_flags);
|
||||
|
||||
if (rq_data_dir(rq) == READ) {
|
||||
unsigned short sectors_per_frame =
|
||||
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
|
||||
@ -695,7 +743,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
|
||||
/* sanity check... */
|
||||
if (rq->current_nr_sectors !=
|
||||
bio_cur_sectors(rq->bio)) {
|
||||
printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
|
||||
printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
|
||||
drive->name, __func__,
|
||||
rq->current_nr_sectors);
|
||||
cdrom_end_request(drive, 0);
|
||||
@ -704,11 +752,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
|
||||
rq->current_nr_sectors += nskip;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
/* the immediate bit */
|
||||
rq->cmd[1] = 1 << 3;
|
||||
#endif
|
||||
|
||||
/* set up the command */
|
||||
rq->timeout = ATAPI_WAIT_PC;
|
||||
|
||||
@ -739,6 +783,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
|
||||
int stat;
|
||||
static int retry = 10;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (cdrom_decode_status(drive, 0, &stat))
|
||||
return ide_stopped;
|
||||
|
||||
@ -746,7 +792,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
|
||||
|
||||
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
|
||||
if (--retry == 0)
|
||||
drive->dsc_overlap = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
}
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -755,6 +801,8 @@ static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
sector_t frame = rq->sector;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
|
||||
|
||||
memset(rq->cmd, 0, BLK_MAX_CDB);
|
||||
@ -775,8 +823,11 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
|
||||
* Fix up a possibly partially-processed request so that we can start it over
|
||||
* entirely, or even put it back on the request queue.
|
||||
*/
|
||||
static void restore_request(struct request *rq)
|
||||
static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (rq->buffer != bio_data(rq->bio)) {
|
||||
sector_t n =
|
||||
(rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
|
||||
@ -795,8 +846,11 @@ static void restore_request(struct request *rq)
|
||||
/*
|
||||
* All other packet commands.
|
||||
*/
|
||||
static void ide_cd_request_sense_fixup(struct request *rq)
|
||||
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
/*
|
||||
* Some of the trailing request sense fields are optional,
|
||||
* and some drives don't send them. Sigh.
|
||||
@ -822,6 +876,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
|
||||
if (!sense)
|
||||
sense = &local_sense;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
|
||||
"timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
|
||||
timeout, cmd_flags);
|
||||
|
||||
/* start of retry loop */
|
||||
do {
|
||||
struct request *rq;
|
||||
@ -895,7 +953,6 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
|
||||
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
xfer_func_t *xferfunc;
|
||||
ide_expiry_t *expiry = NULL;
|
||||
@ -905,13 +962,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
u16 len;
|
||||
u8 ireason;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
|
||||
__func__, rq->cmd[0], write);
|
||||
|
||||
/* check for errors */
|
||||
dma = info->dma;
|
||||
dma = drive->dma;
|
||||
if (dma) {
|
||||
info->dma = 0;
|
||||
drive->dma = 0;
|
||||
dma_error = hwif->dma_ops->dma_end(drive);
|
||||
if (dma_error) {
|
||||
printk(KERN_ERR "%s: DMA %s error\n", drive->name,
|
||||
printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
|
||||
write ? "write" : "read");
|
||||
ide_dma_off(drive);
|
||||
}
|
||||
@ -937,6 +997,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
if (thislen > len)
|
||||
thislen = len;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
|
||||
__func__, stat, thislen);
|
||||
|
||||
/* If DRQ is clear, the command has completed. */
|
||||
if ((stat & ATA_DRQ) == 0) {
|
||||
if (blk_fs_request(rq)) {
|
||||
@ -946,7 +1009,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
*/
|
||||
uptodate = 1;
|
||||
if (rq->current_nr_sectors > 0) {
|
||||
printk(KERN_ERR "%s: %s: data underrun "
|
||||
printk(KERN_ERR PFX "%s: %s: data underrun "
|
||||
"(%d blocks)\n",
|
||||
drive->name, __func__,
|
||||
rq->current_nr_sectors);
|
||||
@ -957,7 +1020,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
cdrom_end_request(drive, uptodate);
|
||||
return ide_stopped;
|
||||
} else if (!blk_pc_request(rq)) {
|
||||
ide_cd_request_sense_fixup(rq);
|
||||
ide_cd_request_sense_fixup(drive, rq);
|
||||
/* complain if we still have data left to transfer */
|
||||
uptodate = rq->data_len ? 0 : 1;
|
||||
}
|
||||
@ -1000,6 +1063,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
xferfunc = hwif->tp_ops->input_data;
|
||||
}
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
|
||||
"ireason: 0x%x\n", __func__, rq->cmd_type, ireason);
|
||||
|
||||
/* transfer data */
|
||||
while (thislen > 0) {
|
||||
u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
|
||||
@ -1024,7 +1090,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
*/
|
||||
ide_pad_transfer(drive, 0, thislen);
|
||||
else {
|
||||
printk(KERN_ERR "%s: confused, missing data\n",
|
||||
printk(KERN_ERR PFX "%s: confused, missing data\n",
|
||||
drive->name);
|
||||
blk_dump_rq_flags(rq, rq_data_dir(rq)
|
||||
? "cdrom_newpc_intr, write"
|
||||
@ -1111,6 +1177,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
|
||||
unsigned short sectors_per_frame =
|
||||
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
|
||||
|
||||
ide_debug_log(IDE_DBG_RQ, "Call %s, write: 0x%x, secs_per_frame: %u\n",
|
||||
__func__, write, sectors_per_frame);
|
||||
|
||||
if (write) {
|
||||
/* disk has become write protected */
|
||||
if (get_disk_ro(cd->disk)) {
|
||||
@ -1122,7 +1191,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
|
||||
* We may be retrying this request after an error. Fix up any
|
||||
* weirdness which might be present in the request packet.
|
||||
*/
|
||||
restore_request(rq);
|
||||
ide_cd_restore_request(drive, rq);
|
||||
}
|
||||
|
||||
/* use DMA, if possible / writes *must* be hardware frame aligned */
|
||||
@ -1132,9 +1201,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
|
||||
cdrom_end_request(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
cd->dma = 0;
|
||||
drive->dma = 0;
|
||||
} else
|
||||
cd->dma = drive->using_dma;
|
||||
drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
||||
|
||||
if (write)
|
||||
cd->devinfo.media_written = 1;
|
||||
@ -1151,14 +1220,16 @@ static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
|
||||
|
||||
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
|
||||
ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd_type: 0x%x\n", __func__,
|
||||
rq->cmd_type);
|
||||
|
||||
if (blk_pc_request(rq))
|
||||
rq->cmd_flags |= REQ_QUIET;
|
||||
else
|
||||
rq->cmd_flags &= ~REQ_FAILED;
|
||||
|
||||
info->dma = 0;
|
||||
drive->dma = 0;
|
||||
|
||||
/* sg request */
|
||||
if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
|
||||
@ -1171,7 +1242,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
|
||||
else
|
||||
buf = rq->data;
|
||||
|
||||
info->dma = drive->using_dma;
|
||||
drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
||||
|
||||
/*
|
||||
* check if dma is safe
|
||||
@ -1182,7 +1253,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
|
||||
alignment = queue_dma_alignment(q) | q->dma_pad_mask;
|
||||
if ((unsigned long)buf & alignment || rq->data_len & alignment
|
||||
|| object_is_on_stack(buf))
|
||||
info->dma = 0;
|
||||
drive->dma = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1196,6 +1267,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
ide_handler_t *fn;
|
||||
int xferlen;
|
||||
|
||||
ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd_type: 0x%x, block: %llu\n",
|
||||
__func__, rq->cmd_type, (unsigned long long)block);
|
||||
|
||||
if (blk_fs_request(rq)) {
|
||||
if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
@ -1208,7 +1282,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
IDECD_SEEK_TIMER);
|
||||
return ide_stopped;
|
||||
}
|
||||
printk(KERN_ERR "%s: DSC timeout\n",
|
||||
printk(KERN_ERR PFX "%s: DSC timeout\n",
|
||||
drive->name);
|
||||
}
|
||||
drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
|
||||
@ -1216,11 +1290,11 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
if (rq_data_dir(rq) == READ &&
|
||||
IDE_LARGE_SEEK(info->last_block, block,
|
||||
IDECD_SEEK_THRESHOLD) &&
|
||||
drive->dsc_overlap) {
|
||||
(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
|
||||
xferlen = 0;
|
||||
fn = cdrom_start_seek_continuation;
|
||||
|
||||
info->dma = 0;
|
||||
drive->dma = 0;
|
||||
info->start_seek = jiffies;
|
||||
|
||||
ide_cd_prepare_seek_request(drive, rq);
|
||||
@ -1249,7 +1323,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
cdrom_end_request(drive, 1);
|
||||
return ide_stopped;
|
||||
} else {
|
||||
blk_dump_rq_flags(rq, "ide-cd bad flags");
|
||||
blk_dump_rq_flags(rq, DRV_NAME " bad flags");
|
||||
cdrom_end_request(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -1279,6 +1353,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
|
||||
struct cdrom_device_info *cdi = &info->devinfo;
|
||||
unsigned char cmd[BLK_MAX_CDB];
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
memset(cmd, 0, BLK_MAX_CDB);
|
||||
cmd[0] = GPCMD_TEST_UNIT_READY;
|
||||
|
||||
@ -1305,6 +1381,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
|
||||
unsigned len = sizeof(capbuf);
|
||||
u32 blocklen;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
memset(cmd, 0, BLK_MAX_CDB);
|
||||
cmd[0] = GPCMD_READ_CDVD_CAPACITY;
|
||||
|
||||
@ -1324,10 +1402,10 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
|
||||
case 4096:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: weird block size %u\n",
|
||||
drive->name, blocklen);
|
||||
printk(KERN_ERR "%s: default to 2kb block size\n",
|
||||
drive->name);
|
||||
printk(KERN_ERR PFX "%s: weird block size %u\n",
|
||||
drive->name, blocklen);
|
||||
printk(KERN_ERR PFX "%s: default to 2kb block size\n",
|
||||
drive->name);
|
||||
blocklen = 2048;
|
||||
break;
|
||||
}
|
||||
@ -1343,6 +1421,8 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
|
||||
{
|
||||
unsigned char cmd[BLK_MAX_CDB];
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
memset(cmd, 0, BLK_MAX_CDB);
|
||||
|
||||
cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
|
||||
@ -1371,11 +1451,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
|
||||
long last_written;
|
||||
unsigned long sectors_per_frame = SECTORS_PER_FRAME;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (toc == NULL) {
|
||||
/* try to allocate space */
|
||||
toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
|
||||
if (toc == NULL) {
|
||||
printk(KERN_ERR "%s: No cdrom TOC buffer!\n",
|
||||
printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
|
||||
drive->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -1531,6 +1613,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
|
||||
struct packet_command cgc;
|
||||
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
|
||||
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
|
||||
|
||||
@ -1549,6 +1633,8 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
|
||||
struct cdrom_info *cd = drive->driver_data;
|
||||
u16 curspeed, maxspeed;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
|
||||
curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
|
||||
maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
|
||||
@ -1589,6 +1675,8 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
struct cdrom_device_info *devinfo = &info->devinfo;
|
||||
|
||||
ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);
|
||||
|
||||
devinfo->ops = &ide_cdrom_dops;
|
||||
devinfo->speed = info->current_speed;
|
||||
devinfo->capacity = nslots;
|
||||
@ -1610,13 +1698,17 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
|
||||
mechtype_t mechtype;
|
||||
int nslots = 1;
|
||||
|
||||
ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
|
||||
"drive->atapi_flags: 0x%lx\n", __func__, drive->media,
|
||||
drive->atapi_flags);
|
||||
|
||||
cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
|
||||
CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
|
||||
CDC_MO_DRIVE | CDC_RAM);
|
||||
|
||||
if (drive->media == ide_optical) {
|
||||
cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
|
||||
printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
|
||||
printk(KERN_ERR PFX "%s: ATAPI magneto-optical drive\n",
|
||||
drive->name);
|
||||
return nslots;
|
||||
}
|
||||
@ -1674,7 +1766,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
|
||||
|
||||
ide_cdrom_update_speed(drive, buf);
|
||||
|
||||
printk(KERN_INFO "%s: ATAPI", drive->name);
|
||||
printk(KERN_INFO PFX "%s: ATAPI", drive->name);
|
||||
|
||||
/* don't print speed if the drive reported 0 */
|
||||
if (cd->max_speed)
|
||||
@ -1697,7 +1789,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
|
||||
else
|
||||
printk(KERN_CONT " drive");
|
||||
|
||||
printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
|
||||
printk(KERN_CONT ", %dkB Cache\n",
|
||||
be16_to_cpup((__be16 *)&buf[8 + 12]));
|
||||
|
||||
return nslots;
|
||||
}
|
||||
@ -1809,7 +1902,7 @@ static ide_proc_entry_t idecd_proc[] = {
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
ide_devset_rw_field(dsc_overlap, dsc_overlap);
|
||||
ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
|
||||
|
||||
static const struct ide_proc_devset idecd_settings[] = {
|
||||
IDE_PROC_DEVSET(dsc_overlap, 0, 1),
|
||||
@ -1884,6 +1977,8 @@ static int ide_cdrom_setup(ide_drive_t *drive)
|
||||
char *fw_rev = (char *)&id[ATA_ID_FW_REV];
|
||||
int nslots;
|
||||
|
||||
ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);
|
||||
|
||||
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
|
||||
blk_queue_dma_alignment(drive->queue, 31);
|
||||
blk_queue_update_dma_pad(drive->queue, 15);
|
||||
@ -1891,14 +1986,9 @@ static int ide_cdrom_setup(ide_drive_t *drive)
|
||||
if (!drive->queue->unplug_delay)
|
||||
drive->queue->unplug_delay = 1;
|
||||
|
||||
drive->special.all = 0;
|
||||
|
||||
drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
|
||||
ide_cd_flags(id);
|
||||
|
||||
if ((id[ATA_ID_CONFIG] & 0x0060) == 0x20)
|
||||
drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
|
||||
|
||||
if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
|
||||
fw_rev[4] == '1' && fw_rev[6] <= '2')
|
||||
drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
|
||||
@ -1915,10 +2005,13 @@ static int ide_cdrom_setup(ide_drive_t *drive)
|
||||
/* set correct block size */
|
||||
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
|
||||
|
||||
drive->dsc_overlap = (drive->next != drive);
|
||||
if (drive->next != drive)
|
||||
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
|
||||
if (ide_cdrom_register(drive, nslots)) {
|
||||
printk(KERN_ERR "%s: %s failed to register device with the"
|
||||
printk(KERN_ERR PFX "%s: %s failed to register device with the"
|
||||
" cdrom driver.\n", drive->name, __func__);
|
||||
cd->devinfo.handle = NULL;
|
||||
return 1;
|
||||
@ -1932,6 +2025,8 @@ static void ide_cd_remove(ide_drive_t *drive)
|
||||
{
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
ide_proc_unregister_driver(drive, info->driver);
|
||||
|
||||
del_gendisk(info->disk);
|
||||
@ -1941,15 +2036,17 @@ static void ide_cd_remove(ide_drive_t *drive)
|
||||
|
||||
static void ide_cd_release(struct kref *kref)
|
||||
{
|
||||
struct cdrom_info *info = to_ide_cd(kref);
|
||||
struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
|
||||
struct cdrom_device_info *devinfo = &info->devinfo;
|
||||
ide_drive_t *drive = info->drive;
|
||||
struct gendisk *g = info->disk;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
kfree(info->toc);
|
||||
if (devinfo->handle == drive)
|
||||
unregister_cdrom(devinfo);
|
||||
drive->dsc_overlap = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
drive->driver_data = NULL;
|
||||
blk_queue_prep_rq(drive->queue, NULL);
|
||||
g->private_data = NULL;
|
||||
@ -1968,7 +2065,6 @@ static ide_driver_t ide_cdrom_driver = {
|
||||
.probe = ide_cd_probe,
|
||||
.remove = ide_cd_remove,
|
||||
.version = IDECD_VERSION,
|
||||
.media = ide_cdrom,
|
||||
.do_request = ide_cd_do_request,
|
||||
.end_request = ide_end_request,
|
||||
.error = __ide_error,
|
||||
@ -1999,7 +2095,7 @@ static int idecd_open(struct inode *inode, struct file *file)
|
||||
static int idecd_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||
struct cdrom_info *info = ide_cd_g(disk);
|
||||
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
|
||||
|
||||
cdrom_release(&info->devinfo, file);
|
||||
|
||||
@ -2051,7 +2147,7 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
|
||||
struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
@ -2072,13 +2168,13 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
static int idecd_media_changed(struct gendisk *disk)
|
||||
{
|
||||
struct cdrom_info *info = ide_cd_g(disk);
|
||||
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
|
||||
return cdrom_media_changed(&info->devinfo);
|
||||
}
|
||||
|
||||
static int idecd_revalidate_disk(struct gendisk *disk)
|
||||
{
|
||||
struct cdrom_info *info = ide_cd_g(disk);
|
||||
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
|
||||
struct request_sense sense;
|
||||
|
||||
ide_cd_read_toc(info->drive, &sense);
|
||||
@ -2097,8 +2193,11 @@ static struct block_device_operations idecd_ops = {
|
||||
|
||||
/* module options */
|
||||
static char *ignore;
|
||||
|
||||
module_param(ignore, charp, 0400);
|
||||
|
||||
static unsigned long debug_mask;
|
||||
module_param(debug_mask, ulong, 0644);
|
||||
|
||||
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
|
||||
|
||||
static int ide_cd_probe(ide_drive_t *drive)
|
||||
@ -2107,6 +2206,10 @@ static int ide_cd_probe(ide_drive_t *drive)
|
||||
struct gendisk *g;
|
||||
struct request_sense sense;
|
||||
|
||||
ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
|
||||
"drive->media: 0x%x\n", __func__, drive->driver_req,
|
||||
drive->media);
|
||||
|
||||
if (!strstr("ide-cdrom", drive->driver_req))
|
||||
goto failed;
|
||||
|
||||
@ -2116,14 +2219,17 @@ static int ide_cd_probe(ide_drive_t *drive)
|
||||
/* skip drives that we were told to ignore */
|
||||
if (ignore != NULL) {
|
||||
if (strstr(ignore, drive->name)) {
|
||||
printk(KERN_INFO "ide-cd: ignoring drive %s\n",
|
||||
printk(KERN_INFO PFX "ignoring drive %s\n",
|
||||
drive->name);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
drive->debug_mask = debug_mask;
|
||||
|
||||
info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
|
||||
if (info == NULL) {
|
||||
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
|
||||
printk(KERN_ERR PFX "%s: Can't allocate a cdrom structure\n",
|
||||
drive->name);
|
||||
goto failed;
|
||||
}
|
||||
@ -2171,6 +2277,7 @@ static void __exit ide_cdrom_exit(void)
|
||||
|
||||
static int __init ide_cdrom_init(void)
|
||||
{
|
||||
printk(KERN_INFO DRV_NAME " driver " IDECD_VERSION "\n");
|
||||
return driver_register(&ide_cdrom_driver.gen_driver);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ struct cdrom_info {
|
||||
struct request_sense sense_data;
|
||||
|
||||
struct request request_sense_request;
|
||||
int dma;
|
||||
unsigned long last_block;
|
||||
unsigned long start_seek;
|
||||
|
||||
|
@ -45,21 +45,12 @@
|
||||
#define IDE_DISK_MINORS 0
|
||||
#endif
|
||||
|
||||
struct ide_disk_obj {
|
||||
ide_drive_t *drive;
|
||||
ide_driver_t *driver;
|
||||
struct gendisk *disk;
|
||||
struct kref kref;
|
||||
unsigned int openers; /* protected by BKL for now */
|
||||
};
|
||||
#include "ide-disk.h"
|
||||
|
||||
static DEFINE_MUTEX(idedisk_ref_mutex);
|
||||
|
||||
#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 void ide_disk_release(struct kref *);
|
||||
|
||||
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
|
||||
@ -140,9 +131,9 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
||||
sector_t block)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned int dma = drive->using_dma;
|
||||
u16 nsectors = (u16)rq->nr_sectors;
|
||||
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
|
||||
u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
|
||||
u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
||||
ide_task_t task;
|
||||
struct ide_taskfile *tf = &task.tf;
|
||||
ide_startstop_t rc;
|
||||
@ -162,7 +153,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
||||
memset(&task, 0, sizeof(task));
|
||||
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
|
||||
if (drive->select.b.lba) {
|
||||
if (drive->dev_flags & IDE_DFLAG_LBA) {
|
||||
if (lba48) {
|
||||
pr_debug("%s: LBA=0x%012llx\n", drive->name,
|
||||
(unsigned long long)block);
|
||||
@ -187,6 +178,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
||||
tf->lbah = block >>= 8;
|
||||
tf->device = (block >> 8) & 0xf;
|
||||
}
|
||||
|
||||
tf->device |= ATA_LBA;
|
||||
} else {
|
||||
unsigned int sect, head, cyl, track;
|
||||
|
||||
@ -237,7 +230,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
||||
BUG_ON(drive->blocked);
|
||||
BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
|
||||
|
||||
if (!blk_fs_request(rq)) {
|
||||
blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
|
||||
@ -384,139 +377,39 @@ static void idedisk_check_hpa(ide_drive_t *drive)
|
||||
static void init_idedisk_capacity(ide_drive_t *drive)
|
||||
{
|
||||
u16 *id = drive->id;
|
||||
/*
|
||||
* If this drive supports the Host Protected Area feature set,
|
||||
* then we may need to change our opinion about the drive's capacity.
|
||||
*/
|
||||
int hpa = ata_id_hpa_enabled(id);
|
||||
int lba;
|
||||
|
||||
if (ata_id_lba48_enabled(id)) {
|
||||
/* drive speaks 48-bit LBA */
|
||||
drive->select.b.lba = 1;
|
||||
lba = 1;
|
||||
drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
|
||||
if (hpa)
|
||||
idedisk_check_hpa(drive);
|
||||
} else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
|
||||
/* drive speaks 28-bit LBA */
|
||||
drive->select.b.lba = 1;
|
||||
lba = 1;
|
||||
drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
|
||||
if (hpa)
|
||||
idedisk_check_hpa(drive);
|
||||
} else {
|
||||
/* drive speaks boring old 28-bit CHS */
|
||||
lba = 0;
|
||||
drive->capacity64 = drive->cyl * drive->head * drive->sect;
|
||||
}
|
||||
|
||||
if (lba) {
|
||||
drive->dev_flags |= IDE_DFLAG_LBA;
|
||||
|
||||
/*
|
||||
* If this device supports the Host Protected Area feature set,
|
||||
* then we may need to change our opinion about its capacity.
|
||||
*/
|
||||
if (ata_id_hpa_enabled(id))
|
||||
idedisk_check_hpa(drive);
|
||||
}
|
||||
}
|
||||
|
||||
static sector_t idedisk_capacity(ide_drive_t *drive)
|
||||
sector_t ide_disk_capacity(ide_drive_t *drive)
|
||||
{
|
||||
return drive->capacity64;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
static int smart_enable(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
tf->feature = ATA_SMART_ENABLE;
|
||||
tf->lbam = ATA_SMART_LBAM_PASS;
|
||||
tf->lbah = ATA_SMART_LBAH_PASS;
|
||||
tf->command = ATA_CMD_SMART;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
return ide_no_data_taskfile(drive, &args);
|
||||
}
|
||||
|
||||
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
tf->feature = sub_cmd;
|
||||
tf->nsect = 0x01;
|
||||
tf->lbam = ATA_SMART_LBAM_PASS;
|
||||
tf->lbah = ATA_SMART_LBAH_PASS;
|
||||
tf->command = ATA_CMD_SMART;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
args.data_phase = TASKFILE_IN;
|
||||
(void) smart_enable(drive);
|
||||
return ide_raw_taskfile(drive, &args, buf, 1);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_cache
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
ide_drive_t *drive = (ide_drive_t *) data;
|
||||
char *out = page;
|
||||
int len;
|
||||
|
||||
if (drive->id_read)
|
||||
len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
|
||||
else
|
||||
len = sprintf(out, "(none)\n");
|
||||
|
||||
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(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data, u8 sub_cmd)
|
||||
{
|
||||
ide_drive_t *drive = (ide_drive_t *)data;
|
||||
int len = 0, i = 0;
|
||||
|
||||
if (get_smart_data(drive, page, sub_cmd) == 0) {
|
||||
unsigned short *val = (unsigned short *) page;
|
||||
char *out = (char *)val + SECTOR_SIZE;
|
||||
|
||||
page = out;
|
||||
do {
|
||||
out += sprintf(out, "%04x%c", le16_to_cpu(*val),
|
||||
(++i & 7) ? ' ' : '\n');
|
||||
val += 1;
|
||||
} while (i < SECTOR_SIZE / 2);
|
||||
len = out - page;
|
||||
}
|
||||
|
||||
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_sv
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
return proc_idedisk_read_smart(page, start, off, count, eof, data,
|
||||
ATA_SMART_READ_VALUES);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_st
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
return proc_idedisk_read_smart(page, start, off, count, eof, data,
|
||||
ATA_SMART_READ_THRESHOLDS);
|
||||
}
|
||||
|
||||
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_sv, NULL },
|
||||
{ "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
#endif /* CONFIG_IDE_PROC_FS */
|
||||
|
||||
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
|
||||
{
|
||||
ide_drive_t *drive = q->queuedata;
|
||||
@ -568,25 +461,43 @@ static int set_multcount(ide_drive_t *drive, int arg)
|
||||
return (drive->mult_count == arg) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
ide_devset_get(nowerr, nowerr);
|
||||
ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
|
||||
|
||||
static int set_nowerr(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
drive->nowerr = arg;
|
||||
if (arg)
|
||||
drive->dev_flags |= IDE_DFLAG_NOWERR;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_NOWERR;
|
||||
|
||||
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
|
||||
{
|
||||
ide_task_t task;
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
task.tf.feature = feature;
|
||||
task.tf.nsect = nsect;
|
||||
task.tf.command = ATA_CMD_SET_FEATURES;
|
||||
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
|
||||
return ide_no_data_taskfile(drive, &task);
|
||||
}
|
||||
|
||||
static void update_ordered(ide_drive_t *drive)
|
||||
{
|
||||
u16 *id = drive->id;
|
||||
unsigned ordered = QUEUE_ORDERED_NONE;
|
||||
prepare_flush_fn *prep_fn = NULL;
|
||||
|
||||
if (drive->wcache) {
|
||||
if (drive->dev_flags & IDE_DFLAG_WCACHE) {
|
||||
unsigned long long capacity;
|
||||
int barrier;
|
||||
/*
|
||||
@ -597,9 +508,11 @@ static void update_ordered(ide_drive_t *drive)
|
||||
* time we have trimmed the drive capacity if LBA48 is
|
||||
* not available so we don't need to recheck that.
|
||||
*/
|
||||
capacity = idedisk_capacity(drive);
|
||||
barrier = ata_id_flush_enabled(id) && !drive->noflush &&
|
||||
(drive->addressing == 0 || capacity <= (1ULL << 28) ||
|
||||
capacity = ide_disk_capacity(drive);
|
||||
barrier = ata_id_flush_enabled(id) &&
|
||||
(drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
|
||||
((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
|
||||
capacity <= (1ULL << 28) ||
|
||||
ata_id_flush_ext_enabled(id));
|
||||
|
||||
printk(KERN_INFO "%s: cache flushes %ssupported\n",
|
||||
@ -615,25 +528,24 @@ static void update_ordered(ide_drive_t *drive)
|
||||
blk_queue_ordered(drive->queue, ordered, prep_fn);
|
||||
}
|
||||
|
||||
ide_devset_get(wcache, wcache);
|
||||
ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
|
||||
|
||||
static int set_wcache(ide_drive_t *drive, int arg)
|
||||
{
|
||||
ide_task_t args;
|
||||
int err = 1;
|
||||
|
||||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ata_id_flush_enabled(drive->id)) {
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tf.feature = arg ?
|
||||
SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
|
||||
args.tf.command = ATA_CMD_SET_FEATURES;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
err = ide_no_data_taskfile(drive, &args);
|
||||
if (err == 0)
|
||||
drive->wcache = arg;
|
||||
err = ide_do_setfeature(drive,
|
||||
arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
|
||||
if (err == 0) {
|
||||
if (arg)
|
||||
drive->dev_flags |= IDE_DFLAG_WCACHE;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_WCACHE;
|
||||
}
|
||||
}
|
||||
|
||||
update_ordered(drive);
|
||||
@ -658,22 +570,18 @@ ide_devset_get(acoustic, acoustic);
|
||||
|
||||
static int set_acoustic(ide_drive_t *drive, int arg)
|
||||
{
|
||||
ide_task_t args;
|
||||
|
||||
if (arg < 0 || arg > 254)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
|
||||
args.tf.nsect = arg;
|
||||
args.tf.command = ATA_CMD_SET_FEATURES;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
ide_no_data_taskfile(drive, &args);
|
||||
ide_do_setfeature(drive,
|
||||
arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
|
||||
|
||||
drive->acoustic = arg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(addressing, addressing);
|
||||
ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
|
||||
|
||||
/*
|
||||
* drive->addressing:
|
||||
@ -686,49 +594,27 @@ static int set_addressing(ide_drive_t *drive, int arg)
|
||||
if (arg < 0 || arg > 2)
|
||||
return -EINVAL;
|
||||
|
||||
drive->addressing = 0;
|
||||
|
||||
if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
|
||||
return 0;
|
||||
|
||||
if (ata_id_lba48_enabled(drive->id) == 0)
|
||||
if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
|
||||
ata_id_lba48_enabled(drive->id) == 0))
|
||||
return -EIO;
|
||||
|
||||
drive->addressing = arg;
|
||||
if (arg == 2)
|
||||
arg = 0;
|
||||
|
||||
if (arg)
|
||||
drive->dev_flags |= IDE_DFLAG_LBA48;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_LBA48;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_rw(acoustic, acoustic);
|
||||
ide_devset_rw(address, addressing);
|
||||
ide_devset_rw(multcount, multcount);
|
||||
ide_devset_rw(wcache, wcache);
|
||||
ide_ext_devset_rw(acoustic, acoustic);
|
||||
ide_ext_devset_rw(address, addressing);
|
||||
ide_ext_devset_rw(multcount, multcount);
|
||||
ide_ext_devset_rw(wcache, wcache);
|
||||
|
||||
ide_devset_rw_sync(nowerr, nowerr);
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
ide_devset_rw_field(failures, failures);
|
||||
ide_devset_rw_field(lun, lun);
|
||||
ide_devset_rw_field(max_failures, max_failures);
|
||||
|
||||
static const struct ide_proc_devset idedisk_settings[] = {
|
||||
IDE_PROC_DEVSET(acoustic, 0, 254),
|
||||
IDE_PROC_DEVSET(address, 0, 2),
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 65535),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(lun, 0, 7),
|
||||
IDE_PROC_DEVSET(max_failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(multcount, 0, 16),
|
||||
IDE_PROC_DEVSET(nowerr, 0, 1),
|
||||
IDE_PROC_DEVSET(wcache, 0, 1),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
ide_ext_devset_rw_sync(nowerr, nowerr);
|
||||
|
||||
static void idedisk_setup(ide_drive_t *drive)
|
||||
{
|
||||
@ -740,20 +626,20 @@ static void idedisk_setup(ide_drive_t *drive)
|
||||
|
||||
ide_proc_register_driver(drive, idkp->driver);
|
||||
|
||||
if (drive->id_read == 0)
|
||||
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
|
||||
return;
|
||||
|
||||
if (drive->removable) {
|
||||
if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
|
||||
/*
|
||||
* Removable disks (eg. SYQUEST); ignore 'WD' drives
|
||||
*/
|
||||
if (m[0] != 'W' || m[1] != 'D')
|
||||
drive->doorlocking = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
|
||||
}
|
||||
|
||||
(void)set_addressing(drive, 1);
|
||||
|
||||
if (drive->addressing == 1) {
|
||||
if (drive->dev_flags & IDE_DFLAG_LBA48) {
|
||||
int max_s = 2048;
|
||||
|
||||
if (max_s > hwif->rqsize)
|
||||
@ -769,7 +655,8 @@ static void idedisk_setup(ide_drive_t *drive)
|
||||
init_idedisk_capacity(drive);
|
||||
|
||||
/* limit drive capacity to 137GB if LBA48 cannot be used */
|
||||
if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
|
||||
drive->capacity64 > 1ULL << 28) {
|
||||
printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
|
||||
"%llu sectors (%llu MB)\n",
|
||||
drive->name, (unsigned long long)drive->capacity64,
|
||||
@ -777,22 +664,23 @@ static void idedisk_setup(ide_drive_t *drive)
|
||||
drive->capacity64 = 1ULL << 28;
|
||||
}
|
||||
|
||||
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
|
||||
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
|
||||
(drive->dev_flags & IDE_DFLAG_LBA48)) {
|
||||
if (drive->capacity64 > 1ULL << 28) {
|
||||
printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
|
||||
" will be used for accessing sectors "
|
||||
"> %u\n", drive->name, 1 << 28);
|
||||
} else
|
||||
drive->addressing = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_LBA48;
|
||||
}
|
||||
|
||||
/*
|
||||
* if possible, give fdisk access to more of the drive,
|
||||
* by correcting bios_cyls:
|
||||
*/
|
||||
capacity = idedisk_capacity(drive);
|
||||
capacity = ide_disk_capacity(drive);
|
||||
|
||||
if (!drive->forced_geom) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
|
||||
if (ata_id_lba48_enabled(drive->id)) {
|
||||
/* compatibility */
|
||||
drive->bios_sect = 63;
|
||||
@ -827,14 +715,15 @@ static void idedisk_setup(ide_drive_t *drive)
|
||||
|
||||
/* write cache enabled? */
|
||||
if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
|
||||
drive->wcache = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_WCACHE;
|
||||
|
||||
set_wcache(drive, 1);
|
||||
}
|
||||
|
||||
static void ide_cacheflush_p(ide_drive_t *drive)
|
||||
{
|
||||
if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0)
|
||||
if (ata_id_flush_enabled(drive->id) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
|
||||
return;
|
||||
|
||||
if (do_idedisk_flushcache(drive))
|
||||
@ -918,13 +807,12 @@ static ide_driver_t idedisk_driver = {
|
||||
.resume = ide_disk_resume,
|
||||
.shutdown = ide_device_shutdown,
|
||||
.version = IDEDISK_VERSION,
|
||||
.media = ide_disk,
|
||||
.do_request = ide_do_rw_disk,
|
||||
.end_request = ide_end_request,
|
||||
.error = __ide_error,
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
.proc = idedisk_proc,
|
||||
.settings = idedisk_settings,
|
||||
.proc = ide_disk_proc,
|
||||
.settings = ide_disk_settings,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -953,15 +841,16 @@ static int idedisk_open(struct inode *inode, struct file *filp)
|
||||
|
||||
idkp->openers++;
|
||||
|
||||
if (drive->removable && idkp->openers == 1) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
|
||||
check_disk_change(inode->i_bdev);
|
||||
/*
|
||||
* Ignore the return code from door_lock,
|
||||
* since the open() has already succeeded,
|
||||
* and the door_lock is irrelevant at this point.
|
||||
*/
|
||||
if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
|
||||
drive->doorlocking = 0;
|
||||
if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
|
||||
idedisk_set_doorlock(drive, 1))
|
||||
drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -975,9 +864,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
|
||||
if (idkp->openers == 1)
|
||||
ide_cacheflush_p(drive);
|
||||
|
||||
if (drive->removable && idkp->openers == 1) {
|
||||
if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
|
||||
drive->doorlocking = 0;
|
||||
if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
|
||||
idedisk_set_doorlock(drive, 0))
|
||||
drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
|
||||
}
|
||||
|
||||
idkp->openers--;
|
||||
@ -998,48 +888,25 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
|
||||
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
|
||||
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
|
||||
{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
|
||||
{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
|
||||
{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int idedisk_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
|
||||
ide_drive_t *drive = idkp->drive;
|
||||
int err;
|
||||
|
||||
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
|
||||
if (err != -EOPNOTSUPP)
|
||||
return err;
|
||||
|
||||
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
|
||||
}
|
||||
|
||||
static int idedisk_media_changed(struct gendisk *disk)
|
||||
{
|
||||
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) {
|
||||
drive->attach = 0;
|
||||
if (drive->dev_flags & IDE_DFLAG_ATTACH) {
|
||||
drive->dev_flags &= ~IDE_DFLAG_ATTACH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if removable, always assume it was changed */
|
||||
return drive->removable;
|
||||
return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
|
||||
}
|
||||
|
||||
static int idedisk_revalidate_disk(struct gendisk *disk)
|
||||
{
|
||||
struct ide_disk_obj *idkp = ide_disk_g(disk);
|
||||
set_capacity(disk, idedisk_capacity(idkp->drive));
|
||||
set_capacity(disk, ide_disk_capacity(idkp->drive));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1047,7 +914,7 @@ static struct block_device_operations idedisk_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = idedisk_open,
|
||||
.release = idedisk_release,
|
||||
.ioctl = idedisk_ioctl,
|
||||
.ioctl = ide_disk_ioctl,
|
||||
.getgeo = idedisk_getgeo,
|
||||
.media_changed = idedisk_media_changed,
|
||||
.revalidate_disk = idedisk_revalidate_disk
|
||||
@ -1088,19 +955,20 @@ static int ide_disk_probe(ide_drive_t *drive)
|
||||
drive->driver_data = idkp;
|
||||
|
||||
idedisk_setup(drive);
|
||||
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
|
||||
(drive->head == 0 || drive->head > 16)) {
|
||||
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
|
||||
drive->name, drive->head);
|
||||
drive->attach = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_ATTACH;
|
||||
} else
|
||||
drive->attach = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_ATTACH;
|
||||
|
||||
g->minors = IDE_DISK_MINORS;
|
||||
g->driverfs_dev = &drive->gendev;
|
||||
g->flags |= GENHD_FL_EXT_DEVT;
|
||||
if (drive->removable)
|
||||
g->flags |= GENHD_FL_REMOVABLE;
|
||||
set_capacity(g, idedisk_capacity(drive));
|
||||
if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
|
||||
g->flags = GENHD_FL_REMOVABLE;
|
||||
set_capacity(g, ide_disk_capacity(drive));
|
||||
g->fops = &idedisk_ops;
|
||||
add_disk(g);
|
||||
return 0;
|
||||
@ -1122,6 +990,7 @@ static int __init idedisk_init(void)
|
||||
}
|
||||
|
||||
MODULE_ALIAS("ide:*m-disk*");
|
||||
MODULE_ALIAS("ide-disk");
|
||||
module_init(idedisk_init);
|
||||
module_exit(idedisk_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
32
drivers/ide/ide-disk.h
Normal file
32
drivers/ide/ide-disk.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef __IDE_DISK_H
|
||||
#define __IDE_DISK_H
|
||||
|
||||
struct ide_disk_obj {
|
||||
ide_drive_t *drive;
|
||||
ide_driver_t *driver;
|
||||
struct gendisk *disk;
|
||||
struct kref kref;
|
||||
unsigned int openers; /* protected by BKL for now */
|
||||
};
|
||||
|
||||
#define ide_disk_g(disk) \
|
||||
container_of((disk)->private_data, struct ide_disk_obj, driver)
|
||||
|
||||
/* ide-disk.c */
|
||||
sector_t ide_disk_capacity(ide_drive_t *);
|
||||
ide_decl_devset(address);
|
||||
ide_decl_devset(multcount);
|
||||
ide_decl_devset(nowerr);
|
||||
ide_decl_devset(wcache);
|
||||
ide_decl_devset(acoustic);
|
||||
|
||||
/* ide-disk_ioctl.c */
|
||||
int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
/* ide-disk_proc.c */
|
||||
extern ide_proc_entry_t ide_disk_proc[];
|
||||
extern const struct ide_proc_devset ide_disk_settings[];
|
||||
#endif
|
||||
|
||||
#endif /* __IDE_DISK_H */
|
29
drivers/ide/ide-disk_ioctl.c
Normal file
29
drivers/ide/ide-disk_ioctl.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/hdreg.h>
|
||||
|
||||
#include "ide-disk.h"
|
||||
|
||||
static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
|
||||
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
|
||||
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
|
||||
{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
|
||||
{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
|
||||
{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
int ide_disk_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
|
||||
ide_drive_t *drive = idkp->drive;
|
||||
int err;
|
||||
|
||||
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
|
||||
if (err != -EOPNOTSUPP)
|
||||
return err;
|
||||
|
||||
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
|
||||
}
|
129
drivers/ide/ide-disk_proc.c
Normal file
129
drivers/ide/ide-disk_proc.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/hdreg.h>
|
||||
|
||||
#include "ide-disk.h"
|
||||
|
||||
static int smart_enable(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
tf->feature = ATA_SMART_ENABLE;
|
||||
tf->lbam = ATA_SMART_LBAM_PASS;
|
||||
tf->lbah = ATA_SMART_LBAH_PASS;
|
||||
tf->command = ATA_CMD_SMART;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
return ide_no_data_taskfile(drive, &args);
|
||||
}
|
||||
|
||||
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
tf->feature = sub_cmd;
|
||||
tf->nsect = 0x01;
|
||||
tf->lbam = ATA_SMART_LBAM_PASS;
|
||||
tf->lbah = ATA_SMART_LBAH_PASS;
|
||||
tf->command = ATA_CMD_SMART;
|
||||
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
args.data_phase = TASKFILE_IN;
|
||||
(void) smart_enable(drive);
|
||||
return ide_raw_taskfile(drive, &args, buf, 1);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_cache
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
ide_drive_t *drive = (ide_drive_t *) data;
|
||||
char *out = page;
|
||||
int len;
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_ID_READ)
|
||||
len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
|
||||
else
|
||||
len = sprintf(out, "(none)\n");
|
||||
|
||||
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)ide_disk_capacity(drive));
|
||||
|
||||
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_smart(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data, u8 sub_cmd)
|
||||
{
|
||||
ide_drive_t *drive = (ide_drive_t *)data;
|
||||
int len = 0, i = 0;
|
||||
|
||||
if (get_smart_data(drive, page, sub_cmd) == 0) {
|
||||
unsigned short *val = (unsigned short *) page;
|
||||
char *out = (char *)val + SECTOR_SIZE;
|
||||
|
||||
page = out;
|
||||
do {
|
||||
out += sprintf(out, "%04x%c", le16_to_cpu(*val),
|
||||
(++i & 7) ? ' ' : '\n');
|
||||
val += 1;
|
||||
} while (i < SECTOR_SIZE / 2);
|
||||
len = out - page;
|
||||
}
|
||||
|
||||
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_sv
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
return proc_idedisk_read_smart(page, start, off, count, eof, data,
|
||||
ATA_SMART_READ_VALUES);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_st
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
return proc_idedisk_read_smart(page, start, off, count, eof, data,
|
||||
ATA_SMART_READ_THRESHOLDS);
|
||||
}
|
||||
|
||||
ide_proc_entry_t ide_disk_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_sv, NULL },
|
||||
{ "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
ide_devset_rw_field(failures, failures);
|
||||
ide_devset_rw_field(lun, lun);
|
||||
ide_devset_rw_field(max_failures, max_failures);
|
||||
|
||||
const struct ide_proc_devset ide_disk_settings[] = {
|
||||
IDE_PROC_DEVSET(acoustic, 0, 254),
|
||||
IDE_PROC_DEVSET(address, 0, 2),
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 65535),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(lun, 0, 7),
|
||||
IDE_PROC_DEVSET(max_failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(multcount, 0, 16),
|
||||
IDE_PROC_DEVSET(nowerr, 0, 1),
|
||||
IDE_PROC_DEVSET(wcache, 0, 1),
|
||||
{ 0 },
|
||||
};
|
356
drivers/ide/ide-dma-sff.c
Normal file
356
drivers/ide/ide-dma-sff.c
Normal file
@ -0,0 +1,356 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
/**
|
||||
* config_drive_for_dma - attempt to activate IDE DMA
|
||||
* @drive: the drive to place in DMA mode
|
||||
*
|
||||
* If the drive supports at least mode 2 DMA or UDMA of any kind
|
||||
* then attempt to place it into DMA mode. Drives that are known to
|
||||
* support DMA but predate the DMA properties or that are known
|
||||
* to have DMA handling bugs are also set up appropriately based
|
||||
* on the good/bad drive lists.
|
||||
*/
|
||||
|
||||
int config_drive_for_dma(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u16 *id = drive->id;
|
||||
|
||||
if (drive->media != ide_disk) {
|
||||
if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable DMA on any drive that has
|
||||
* UltraDMA (mode 0/1/2/3/4/5/6) enabled
|
||||
*/
|
||||
if ((id[ATA_ID_FIELD_VALID] & 4) &&
|
||||
((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Enable DMA on any drive that has mode2 DMA
|
||||
* (multi or single) enabled
|
||||
*/
|
||||
if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
|
||||
if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
|
||||
(id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
|
||||
return 1;
|
||||
|
||||
/* Consult the list of known "good" drives */
|
||||
if (ide_dma_good_drive(drive))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_dma_host_set - Enable/disable DMA on a host
|
||||
* @drive: drive to control
|
||||
*
|
||||
* Enable/disable DMA on an IDE controller following generic
|
||||
* bus-mastering IDE controller behaviour.
|
||||
*/
|
||||
|
||||
void ide_dma_host_set(ide_drive_t *drive, int on)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 unit = drive->dn & 1;
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
if (on)
|
||||
dma_stat |= (1 << (5 + unit));
|
||||
else
|
||||
dma_stat &= ~(1 << (5 + unit));
|
||||
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO)
|
||||
writeb(dma_stat,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_host_set);
|
||||
|
||||
/**
|
||||
* ide_build_dmatable - build IDE DMA table
|
||||
*
|
||||
* ide_build_dmatable() prepares a dma request. We map the command
|
||||
* to get the pci bus addresses of the buffers and then build up
|
||||
* the PRD table that the IDE layer wants to be fed.
|
||||
*
|
||||
* Most chipsets correctly interpret a length of 0x0000 as 64KB,
|
||||
* but at least one (e.g. CS5530) misinterprets it as zero (!).
|
||||
* So we break the 64KB entry into two 32KB entries instead.
|
||||
*
|
||||
* Returns the number of built PRD entries if all went okay,
|
||||
* returns 0 otherwise.
|
||||
*
|
||||
* May also be invoked from trm290.c
|
||||
*/
|
||||
|
||||
int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
__le32 *table = (__le32 *)hwif->dmatable_cpu;
|
||||
unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
|
||||
unsigned int count = 0;
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
|
||||
hwif->sg_nents = ide_build_sglist(drive, rq);
|
||||
if (hwif->sg_nents == 0)
|
||||
return 0;
|
||||
|
||||
for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
|
||||
u32 cur_addr, cur_len, xcount, bcount;
|
||||
|
||||
cur_addr = sg_dma_address(sg);
|
||||
cur_len = sg_dma_len(sg);
|
||||
|
||||
/*
|
||||
* Fill in the dma table, without crossing any 64kB boundaries.
|
||||
* Most hardware requires 16-bit alignment of all blocks,
|
||||
* but the trm290 requires 32-bit alignment.
|
||||
*/
|
||||
|
||||
while (cur_len) {
|
||||
if (count++ >= PRD_ENTRIES)
|
||||
goto use_pio_instead;
|
||||
|
||||
bcount = 0x10000 - (cur_addr & 0xffff);
|
||||
if (bcount > cur_len)
|
||||
bcount = cur_len;
|
||||
*table++ = cpu_to_le32(cur_addr);
|
||||
xcount = bcount & 0xffff;
|
||||
if (is_trm290)
|
||||
xcount = ((xcount >> 2) - 1) << 16;
|
||||
if (xcount == 0x0000) {
|
||||
if (count++ >= PRD_ENTRIES)
|
||||
goto use_pio_instead;
|
||||
*table++ = cpu_to_le32(0x8000);
|
||||
*table++ = cpu_to_le32(cur_addr + 0x8000);
|
||||
xcount = 0x8000;
|
||||
}
|
||||
*table++ = cpu_to_le32(xcount);
|
||||
cur_addr += bcount;
|
||||
cur_len -= bcount;
|
||||
}
|
||||
}
|
||||
|
||||
if (count) {
|
||||
if (!is_trm290)
|
||||
*--table |= cpu_to_le32(0x80000000);
|
||||
return count;
|
||||
}
|
||||
|
||||
use_pio_instead:
|
||||
printk(KERN_ERR "%s: %s\n", drive->name,
|
||||
count ? "DMA table too small" : "empty DMA table?");
|
||||
|
||||
ide_destroy_dmatable(drive);
|
||||
|
||||
return 0; /* revert to PIO for this request */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_build_dmatable);
|
||||
|
||||
/**
|
||||
* ide_dma_setup - begin a DMA phase
|
||||
* @drive: target device
|
||||
*
|
||||
* Build an IDE DMA PRD (IDE speak for scatter gather table)
|
||||
* and then set up the DMA transfer registers for a device
|
||||
* that follows generic IDE PCI DMA behaviour. Controllers can
|
||||
* override this function if they need to
|
||||
*
|
||||
* Returns 0 on success. If a PIO fallback is required then 1
|
||||
* is returned.
|
||||
*/
|
||||
|
||||
int ide_dma_setup(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
unsigned int reading;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat;
|
||||
|
||||
if (rq_data_dir(rq))
|
||||
reading = 0;
|
||||
else
|
||||
reading = 1 << 3;
|
||||
|
||||
/* fall back to pio! */
|
||||
if (!ide_build_dmatable(drive, rq)) {
|
||||
ide_map_sg(drive, rq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* PRD table */
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO)
|
||||
writel(hwif->dmatable_dma,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
|
||||
else
|
||||
outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
|
||||
|
||||
/* specify r/w */
|
||||
if (mmio)
|
||||
writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
else
|
||||
outb(reading, hwif->dma_base + ATA_DMA_CMD);
|
||||
|
||||
/* read DMA status for INTR & ERROR flags */
|
||||
dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
/* clear INTR & ERROR flags */
|
||||
if (mmio)
|
||||
writeb(dma_stat | 6,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
drive->waiting_for_dma = 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_setup);
|
||||
|
||||
/**
|
||||
* dma_timer_expiry - handle a DMA timeout
|
||||
* @drive: Drive that timed out
|
||||
*
|
||||
* An IDE DMA transfer timed out. In the event of an error we ask
|
||||
* the driver to resolve the problem, if a DMA transfer is still
|
||||
* in progress we continue to wait (arguably we need to add a
|
||||
* secondary 'I don't care what the drive thinks' timeout here)
|
||||
* Finally if we have an interrupt we let it complete the I/O.
|
||||
* But only one time - we clear expiry and if it's still not
|
||||
* completed after WAIT_CMD, we error and retry in PIO.
|
||||
* This can occur if an interrupt is lost or due to hang or bugs.
|
||||
*/
|
||||
|
||||
static int dma_timer_expiry(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
|
||||
drive->name, __func__, dma_stat);
|
||||
|
||||
if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
|
||||
return WAIT_CMD;
|
||||
|
||||
hwif->hwgroup->expiry = NULL; /* one free ride for now */
|
||||
|
||||
/* 1 dmaing, 2 error, 4 intr */
|
||||
if (dma_stat & 2) /* ERROR */
|
||||
return -1;
|
||||
|
||||
if (dma_stat & 1) /* DMAing */
|
||||
return WAIT_CMD;
|
||||
|
||||
if (dma_stat & 4) /* Got an Interrupt */
|
||||
return WAIT_CMD;
|
||||
|
||||
return 0; /* Status is unknown -- reset the bus */
|
||||
}
|
||||
|
||||
void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
|
||||
{
|
||||
/* issue cmd to drive */
|
||||
ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
|
||||
dma_timer_expiry);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
|
||||
|
||||
void ide_dma_start(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 dma_cmd;
|
||||
|
||||
/* Note that this is done *after* the cmd has
|
||||
* been issued to the drive, as per the BM-IDE spec.
|
||||
* The Promise Ultra33 doesn't work correctly when
|
||||
* we do this part before issuing the drive cmd.
|
||||
*/
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO) {
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* start DMA */
|
||||
writeb(dma_cmd | 1,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
wmb();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_start);
|
||||
|
||||
/* returns 1 on error, 0 otherwise */
|
||||
int ide_dma_end(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat = 0, dma_cmd = 0;
|
||||
|
||||
drive->waiting_for_dma = 0;
|
||||
|
||||
if (mmio) {
|
||||
/* get DMA command mode */
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* stop DMA */
|
||||
writeb(dma_cmd & ~1,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
/* get DMA status */
|
||||
dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
if (mmio)
|
||||
/* clear the INTR & ERROR bits */
|
||||
writeb(dma_stat | 6,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
/* purge DMA mappings */
|
||||
ide_destroy_dmatable(drive);
|
||||
/* verify good DMA status */
|
||||
wmb();
|
||||
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_end);
|
||||
|
||||
/* returns 1 if dma irq issued, 0 otherwise */
|
||||
int ide_dma_test_irq(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
/* return 1 if INTR asserted */
|
||||
if ((dma_stat & 4) == 4)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_test_irq);
|
||||
|
||||
const struct ide_dma_ops sff_dma_ops = {
|
||||
.dma_host_set = ide_dma_host_set,
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = ide_dma_test_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sff_dma_ops);
|
@ -28,24 +28,13 @@
|
||||
* for supplying a Promise UDMA board & WD UDMA drive for this work!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
static const struct drive_list_entry drive_whitelist [] = {
|
||||
|
||||
static const struct drive_list_entry drive_whitelist[] = {
|
||||
{ "Micropolis 2112A" , NULL },
|
||||
{ "CONNER CTMA 4000" , NULL },
|
||||
{ "CONNER CTT8000-A" , NULL },
|
||||
@ -53,8 +42,7 @@ static const struct drive_list_entry drive_whitelist [] = {
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
static const struct drive_list_entry drive_blacklist [] = {
|
||||
|
||||
static const struct drive_list_entry drive_blacklist[] = {
|
||||
{ "WDC AC11000H" , NULL },
|
||||
{ "WDC AC22100H" , NULL },
|
||||
{ "WDC AC32500H" , NULL },
|
||||
@ -94,11 +82,11 @@ static const struct drive_list_entry drive_blacklist [] = {
|
||||
* ide_dma_intr - IDE DMA interrupt handler
|
||||
* @drive: the drive the interrupt is for
|
||||
*
|
||||
* Handle an interrupt completing a read/write DMA transfer on an
|
||||
* Handle an interrupt completing a read/write DMA transfer on an
|
||||
* IDE device
|
||||
*/
|
||||
|
||||
ide_startstop_t ide_dma_intr (ide_drive_t *drive)
|
||||
|
||||
ide_startstop_t ide_dma_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 stat = 0, dma_stat = 0;
|
||||
@ -108,20 +96,19 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
|
||||
|
||||
if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
|
||||
if (!dma_stat) {
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
|
||||
task_end_request(drive, rq, stat);
|
||||
return ide_stopped;
|
||||
}
|
||||
printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
|
||||
drive->name, dma_stat);
|
||||
printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
|
||||
drive->name, __func__, dma_stat);
|
||||
}
|
||||
return ide_error(drive, "dma_intr", stat);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_dma_intr);
|
||||
|
||||
static int ide_dma_good_drive(ide_drive_t *drive)
|
||||
int ide_dma_good_drive(ide_drive_t *drive)
|
||||
{
|
||||
return ide_in_drive_list(drive->id, drive_whitelist);
|
||||
}
|
||||
@ -139,7 +126,7 @@ static int ide_dma_good_drive(ide_drive_t *drive)
|
||||
|
||||
int ide_build_sglist(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct scatterlist *sg = hwif->sg_table;
|
||||
|
||||
ide_map_sg(drive, rq);
|
||||
@ -152,106 +139,8 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
|
||||
return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
|
||||
hwif->sg_dma_direction);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_build_sglist);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
|
||||
/**
|
||||
* ide_build_dmatable - build IDE DMA table
|
||||
*
|
||||
* ide_build_dmatable() prepares a dma request. We map the command
|
||||
* to get the pci bus addresses of the buffers and then build up
|
||||
* the PRD table that the IDE layer wants to be fed. The code
|
||||
* knows about the 64K wrap bug in the CS5530.
|
||||
*
|
||||
* Returns the number of built PRD entries if all went okay,
|
||||
* returns 0 otherwise.
|
||||
*
|
||||
* May also be invoked from trm290.c
|
||||
*/
|
||||
|
||||
int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
__le32 *table = (__le32 *)hwif->dmatable_cpu;
|
||||
unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
|
||||
unsigned int count = 0;
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
|
||||
hwif->sg_nents = i = ide_build_sglist(drive, rq);
|
||||
|
||||
if (!i)
|
||||
return 0;
|
||||
|
||||
sg = hwif->sg_table;
|
||||
while (i) {
|
||||
u32 cur_addr;
|
||||
u32 cur_len;
|
||||
|
||||
cur_addr = sg_dma_address(sg);
|
||||
cur_len = sg_dma_len(sg);
|
||||
|
||||
/*
|
||||
* Fill in the dma table, without crossing any 64kB boundaries.
|
||||
* Most hardware requires 16-bit alignment of all blocks,
|
||||
* but the trm290 requires 32-bit alignment.
|
||||
*/
|
||||
|
||||
while (cur_len) {
|
||||
if (count++ >= PRD_ENTRIES) {
|
||||
printk(KERN_ERR "%s: DMA table too small\n", drive->name);
|
||||
goto use_pio_instead;
|
||||
} else {
|
||||
u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
|
||||
|
||||
if (bcount > cur_len)
|
||||
bcount = cur_len;
|
||||
*table++ = cpu_to_le32(cur_addr);
|
||||
xcount = bcount & 0xffff;
|
||||
if (is_trm290)
|
||||
xcount = ((xcount >> 2) - 1) << 16;
|
||||
else if (xcount == 0x0000) {
|
||||
/*
|
||||
* Most chipsets correctly interpret a length of 0x0000 as 64KB,
|
||||
* but at least one (e.g. CS5530) misinterprets it as zero (!).
|
||||
* So here we break the 64KB entry into two 32KB entries instead.
|
||||
*/
|
||||
if (count++ >= PRD_ENTRIES) {
|
||||
printk(KERN_ERR "%s: DMA table too small\n", drive->name);
|
||||
goto use_pio_instead;
|
||||
}
|
||||
*table++ = cpu_to_le32(0x8000);
|
||||
*table++ = cpu_to_le32(cur_addr + 0x8000);
|
||||
xcount = 0x8000;
|
||||
}
|
||||
*table++ = cpu_to_le32(xcount);
|
||||
cur_addr += bcount;
|
||||
cur_len -= bcount;
|
||||
}
|
||||
}
|
||||
|
||||
sg = sg_next(sg);
|
||||
i--;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
if (!is_trm290)
|
||||
*--table |= cpu_to_le32(0x80000000);
|
||||
return count;
|
||||
}
|
||||
|
||||
printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
|
||||
|
||||
use_pio_instead:
|
||||
ide_destroy_dmatable(drive);
|
||||
|
||||
return 0; /* revert to PIO for this request */
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_build_dmatable);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ide_destroy_dmatable - clean up DMA mapping
|
||||
* @drive: The drive to unmap
|
||||
@ -262,147 +151,30 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
|
||||
* an oops as only one mapping can be live for each target at a given
|
||||
* time.
|
||||
*/
|
||||
|
||||
void ide_destroy_dmatable (ide_drive_t *drive)
|
||||
|
||||
void ide_destroy_dmatable(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
|
||||
hwif->sg_dma_direction);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
|
||||
/**
|
||||
* config_drive_for_dma - attempt to activate IDE DMA
|
||||
* @drive: the drive to place in DMA mode
|
||||
*
|
||||
* If the drive supports at least mode 2 DMA or UDMA of any kind
|
||||
* then attempt to place it into DMA mode. Drives that are known to
|
||||
* support DMA but predate the DMA properties or that are known
|
||||
* to have DMA handling bugs are also set up appropriately based
|
||||
* on the good/bad drive lists.
|
||||
*/
|
||||
|
||||
static int config_drive_for_dma (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u16 *id = drive->id;
|
||||
|
||||
if (drive->media != ide_disk) {
|
||||
if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable DMA on any drive that has
|
||||
* UltraDMA (mode 0/1/2/3/4/5/6) enabled
|
||||
*/
|
||||
if ((id[ATA_ID_FIELD_VALID] & 4) &&
|
||||
((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Enable DMA on any drive that has mode2 DMA
|
||||
* (multi or single) enabled
|
||||
*/
|
||||
if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
|
||||
if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
|
||||
(id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
|
||||
return 1;
|
||||
|
||||
/* Consult the list of known "good" drives */
|
||||
if (ide_dma_good_drive(drive))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_timer_expiry - handle a DMA timeout
|
||||
* @drive: Drive that timed out
|
||||
*
|
||||
* An IDE DMA transfer timed out. In the event of an error we ask
|
||||
* the driver to resolve the problem, if a DMA transfer is still
|
||||
* in progress we continue to wait (arguably we need to add a
|
||||
* secondary 'I don't care what the drive thinks' timeout here)
|
||||
* Finally if we have an interrupt we let it complete the I/O.
|
||||
* But only one time - we clear expiry and if it's still not
|
||||
* completed after WAIT_CMD, we error and retry in PIO.
|
||||
* This can occur if an interrupt is lost or due to hang or bugs.
|
||||
*/
|
||||
|
||||
static int dma_timer_expiry (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
|
||||
drive->name, dma_stat);
|
||||
|
||||
if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
|
||||
return WAIT_CMD;
|
||||
|
||||
HWGROUP(drive)->expiry = NULL; /* one free ride for now */
|
||||
|
||||
/* 1 dmaing, 2 error, 4 intr */
|
||||
if (dma_stat & 2) /* ERROR */
|
||||
return -1;
|
||||
|
||||
if (dma_stat & 1) /* DMAing */
|
||||
return WAIT_CMD;
|
||||
|
||||
if (dma_stat & 4) /* Got an Interrupt */
|
||||
return WAIT_CMD;
|
||||
|
||||
return 0; /* Status is unknown -- reset the bus */
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_dma_host_set - Enable/disable DMA on a host
|
||||
* @drive: drive to control
|
||||
*
|
||||
* Enable/disable DMA on an IDE controller following generic
|
||||
* bus-mastering IDE controller behaviour.
|
||||
*/
|
||||
|
||||
void ide_dma_host_set(ide_drive_t *drive, int on)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
if (on)
|
||||
dma_stat |= (1 << (5 + unit));
|
||||
else
|
||||
dma_stat &= ~(1 << (5 + unit));
|
||||
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO)
|
||||
writeb(dma_stat,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_dma_host_set);
|
||||
#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
|
||||
|
||||
/**
|
||||
* ide_dma_off_quietly - Generic DMA kill
|
||||
* @drive: drive to control
|
||||
*
|
||||
* Turn off the current DMA on this IDE controller.
|
||||
* Turn off the current DMA on this IDE controller.
|
||||
*/
|
||||
|
||||
void ide_dma_off_quietly(ide_drive_t *drive)
|
||||
{
|
||||
drive->using_dma = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_USING_DMA;
|
||||
ide_toggle_bounce(drive, 0);
|
||||
|
||||
drive->hwif->dma_ops->dma_host_set(drive, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_dma_off_quietly);
|
||||
|
||||
/**
|
||||
@ -418,7 +190,6 @@ void ide_dma_off(ide_drive_t *drive)
|
||||
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
|
||||
ide_dma_off_quietly(drive);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_dma_off);
|
||||
|
||||
/**
|
||||
@ -430,167 +201,13 @@ EXPORT_SYMBOL(ide_dma_off);
|
||||
|
||||
void ide_dma_on(ide_drive_t *drive)
|
||||
{
|
||||
drive->using_dma = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_USING_DMA;
|
||||
ide_toggle_bounce(drive, 1);
|
||||
|
||||
drive->hwif->dma_ops->dma_host_set(drive, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
|
||||
/**
|
||||
* ide_dma_setup - begin a DMA phase
|
||||
* @drive: target device
|
||||
*
|
||||
* Build an IDE DMA PRD (IDE speak for scatter gather table)
|
||||
* and then set up the DMA transfer registers for a device
|
||||
* that follows generic IDE PCI DMA behaviour. Controllers can
|
||||
* override this function if they need to
|
||||
*
|
||||
* Returns 0 on success. If a PIO fallback is required then 1
|
||||
* is returned.
|
||||
*/
|
||||
|
||||
int ide_dma_setup(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
unsigned int reading;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat;
|
||||
|
||||
if (rq_data_dir(rq))
|
||||
reading = 0;
|
||||
else
|
||||
reading = 1 << 3;
|
||||
|
||||
/* fall back to pio! */
|
||||
if (!ide_build_dmatable(drive, rq)) {
|
||||
ide_map_sg(drive, rq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* PRD table */
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO)
|
||||
writel(hwif->dmatable_dma,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
|
||||
else
|
||||
outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
|
||||
|
||||
/* specify r/w */
|
||||
if (mmio)
|
||||
writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
else
|
||||
outb(reading, hwif->dma_base + ATA_DMA_CMD);
|
||||
|
||||
/* read DMA status for INTR & ERROR flags */
|
||||
dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
/* clear INTR & ERROR flags */
|
||||
if (mmio)
|
||||
writeb(dma_stat | 6,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
drive->waiting_for_dma = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_dma_setup);
|
||||
|
||||
void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
|
||||
{
|
||||
/* issue cmd to drive */
|
||||
ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
|
||||
|
||||
void ide_dma_start(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 dma_cmd;
|
||||
|
||||
/* Note that this is done *after* the cmd has
|
||||
* been issued to the drive, as per the BM-IDE spec.
|
||||
* The Promise Ultra33 doesn't work correctly when
|
||||
* we do this part before issuing the drive cmd.
|
||||
*/
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO) {
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* start DMA */
|
||||
writeb(dma_cmd | 1,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
hwif->dma = 1;
|
||||
wmb();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_dma_start);
|
||||
|
||||
/* returns 1 on error, 0 otherwise */
|
||||
int __ide_dma_end (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat = 0, dma_cmd = 0;
|
||||
|
||||
drive->waiting_for_dma = 0;
|
||||
|
||||
if (mmio) {
|
||||
/* get DMA command mode */
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* stop DMA */
|
||||
writeb(dma_cmd & ~1,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
/* get DMA status */
|
||||
dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
if (mmio)
|
||||
/* clear the INTR & ERROR bits */
|
||||
writeb(dma_stat | 6,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
/* purge DMA mappings */
|
||||
ide_destroy_dmatable(drive);
|
||||
/* verify good DMA status */
|
||||
hwif->dma = 0;
|
||||
wmb();
|
||||
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__ide_dma_end);
|
||||
|
||||
/* returns 1 if dma irq issued, 0 otherwise */
|
||||
int ide_dma_test_irq(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
/* return 1 if INTR asserted */
|
||||
if ((dma_stat & 4) == 4)
|
||||
return 1;
|
||||
if (!drive->waiting_for_dma)
|
||||
printk(KERN_WARNING "%s: (%s) called while not waiting\n",
|
||||
drive->name, __func__);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_test_irq);
|
||||
#else
|
||||
static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
|
||||
#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
|
||||
|
||||
int __ide_dma_bad_drive (ide_drive_t *drive)
|
||||
int __ide_dma_bad_drive(ide_drive_t *drive)
|
||||
{
|
||||
u16 *id = drive->id;
|
||||
|
||||
@ -602,7 +219,6 @@ int __ide_dma_bad_drive (ide_drive_t *drive)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__ide_dma_bad_drive);
|
||||
|
||||
static const u8 xfer_mode_bases[] = {
|
||||
@ -618,7 +234,7 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
|
||||
const struct ide_port_ops *port_ops = hwif->port_ops;
|
||||
unsigned int mask = 0;
|
||||
|
||||
switch(base) {
|
||||
switch (base) {
|
||||
case XFER_UDMA_0:
|
||||
if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
|
||||
break;
|
||||
@ -719,7 +335,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
|
||||
|
||||
static int ide_tune_dma(ide_drive_t *drive)
|
||||
@ -727,7 +342,8 @@ static int ide_tune_dma(ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 speed;
|
||||
|
||||
if (drive->nodma || ata_id_has_dma(drive->id) == 0)
|
||||
if (ata_id_has_dma(drive->id) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_NODMA))
|
||||
return 0;
|
||||
|
||||
/* consult the list of known "bad" drives */
|
||||
@ -827,66 +443,59 @@ void ide_check_dma_crc(ide_drive_t *drive)
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
|
||||
void ide_dma_lost_irq (ide_drive_t *drive)
|
||||
void ide_dma_lost_irq(ide_drive_t *drive)
|
||||
{
|
||||
printk("%s: DMA interrupt recovery\n", drive->name);
|
||||
printk(KERN_ERR "%s: DMA interrupt recovery\n", drive->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_lost_irq);
|
||||
|
||||
EXPORT_SYMBOL(ide_dma_lost_irq);
|
||||
|
||||
void ide_dma_timeout (ide_drive_t *drive)
|
||||
void ide_dma_timeout(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
|
||||
|
||||
if (hwif->dma_ops->dma_test_irq(drive))
|
||||
return;
|
||||
|
||||
ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
|
||||
|
||||
hwif->dma_ops->dma_end(drive);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_dma_timeout);
|
||||
EXPORT_SYMBOL_GPL(ide_dma_timeout);
|
||||
|
||||
void ide_release_dma_engine(ide_hwif_t *hwif)
|
||||
{
|
||||
if (hwif->dmatable_cpu) {
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
int prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
|
||||
|
||||
pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
|
||||
hwif->dmatable_cpu, hwif->dmatable_dma);
|
||||
dma_free_coherent(hwif->dev, prd_size,
|
||||
hwif->dmatable_cpu, hwif->dmatable_dma);
|
||||
hwif->dmatable_cpu = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_release_dma_engine);
|
||||
|
||||
int ide_allocate_dma_engine(ide_hwif_t *hwif)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
int prd_size;
|
||||
|
||||
hwif->dmatable_cpu = pci_alloc_consistent(pdev,
|
||||
PRD_ENTRIES * PRD_BYTES,
|
||||
&hwif->dmatable_dma);
|
||||
if (hwif->prd_max_nents == 0)
|
||||
hwif->prd_max_nents = PRD_ENTRIES;
|
||||
if (hwif->prd_ent_size == 0)
|
||||
hwif->prd_ent_size = PRD_BYTES;
|
||||
|
||||
if (hwif->dmatable_cpu)
|
||||
return 0;
|
||||
prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
|
||||
|
||||
printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
|
||||
hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, prd_size,
|
||||
&hwif->dmatable_dma,
|
||||
GFP_ATOMIC);
|
||||
if (hwif->dmatable_cpu == NULL) {
|
||||
printk(KERN_ERR "%s: unable to allocate PRD table\n",
|
||||
hwif->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
|
||||
|
||||
const struct ide_dma_ops sff_dma_ops = {
|
||||
.dma_host_set = ide_dma_host_set,
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_test_irq = ide_dma_test_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sff_dma_ops);
|
||||
#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#define DRV_NAME "ide-floppy"
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
#define IDEFLOPPY_VERSION "1.00"
|
||||
|
||||
@ -48,17 +49,17 @@
|
||||
|
||||
#include "ide-floppy.h"
|
||||
|
||||
/* define to see debug info */
|
||||
#define IDEFLOPPY_DEBUG_LOG 0
|
||||
/* module parameters */
|
||||
static unsigned long debug_mask;
|
||||
module_param(debug_mask, ulong, 0644);
|
||||
|
||||
/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
|
||||
#define IDEFLOPPY_DEBUG(fmt, args...)
|
||||
/* define to see debug info */
|
||||
#define IDEFLOPPY_DEBUG_LOG 0
|
||||
|
||||
#if IDEFLOPPY_DEBUG_LOG
|
||||
#define debug_log(fmt, args...) \
|
||||
printk(KERN_INFO "ide-floppy: " fmt, ## args)
|
||||
#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
|
||||
#else
|
||||
#define debug_log(fmt, args...) do {} while (0)
|
||||
#define ide_debug_log(lvl, fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -73,18 +74,17 @@
|
||||
#define CAPACITY_CURRENT 0x02
|
||||
#define CAPACITY_NO_CARTRIDGE 0x03
|
||||
|
||||
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
|
||||
/*
|
||||
* The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
|
||||
* was apparently being deasserted before the unit was ready to receive data.
|
||||
*/
|
||||
#define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */
|
||||
|
||||
/* Error code returned in rq->errors to the higher part of the driver. */
|
||||
#define IDEFLOPPY_ERROR_GENERAL 101
|
||||
|
||||
static DEFINE_MUTEX(idefloppy_ref_mutex);
|
||||
|
||||
#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 void idefloppy_cleanup_obj(struct kref *);
|
||||
|
||||
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
|
||||
@ -92,7 +92,7 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
|
||||
struct ide_floppy_obj *floppy = NULL;
|
||||
|
||||
mutex_lock(&idefloppy_ref_mutex);
|
||||
floppy = ide_floppy_g(disk);
|
||||
floppy = ide_drv_g(disk, ide_floppy_obj);
|
||||
if (floppy) {
|
||||
if (ide_device_get(floppy->drive))
|
||||
floppy = NULL;
|
||||
@ -123,13 +123,21 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
int error;
|
||||
|
||||
debug_log("Reached %s\n", __func__);
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
switch (uptodate) {
|
||||
case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
|
||||
case 1: error = 0; break;
|
||||
default: error = uptodate;
|
||||
case 0:
|
||||
error = IDEFLOPPY_ERROR_GENERAL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = uptodate;
|
||||
}
|
||||
|
||||
if (error)
|
||||
floppy->failed_pc = NULL;
|
||||
/* Why does this happen? */
|
||||
@ -156,13 +164,13 @@ static void idefloppy_update_buffers(ide_drive_t *drive,
|
||||
idefloppy_end_request(drive, 1, 0);
|
||||
}
|
||||
|
||||
static void ide_floppy_callback(ide_drive_t *drive)
|
||||
static void ide_floppy_callback(ide_drive_t *drive, int dsc)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
struct ide_atapi_pc *pc = floppy->pc;
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
int uptodate = pc->error ? 0 : 1;
|
||||
|
||||
debug_log("Reached %s\n", __func__);
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (floppy->failed_pc == pc)
|
||||
floppy->failed_pc = NULL;
|
||||
@ -171,7 +179,7 @@ static void ide_floppy_callback(ide_drive_t *drive)
|
||||
(pc->rq && blk_pc_request(pc->rq)))
|
||||
uptodate = 1; /* FIXME */
|
||||
else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
|
||||
u8 *buf = floppy->pc->buf;
|
||||
u8 *buf = pc->buf;
|
||||
|
||||
if (!pc->error) {
|
||||
floppy->sense_key = buf[2] & 0x0F;
|
||||
@ -181,99 +189,20 @@ static void ide_floppy_callback(ide_drive_t *drive)
|
||||
(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
|
||||
|
||||
if (floppy->failed_pc)
|
||||
debug_log("pc = %x, ", floppy->failed_pc->c[0]);
|
||||
ide_debug_log(IDE_DBG_PC, "pc = %x, ",
|
||||
floppy->failed_pc->c[0]);
|
||||
|
||||
debug_log("sense key = %x, asc = %x, ascq = %x\n",
|
||||
floppy->sense_key, floppy->asc, floppy->ascq);
|
||||
ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
|
||||
"ascq = %x\n", floppy->sense_key,
|
||||
floppy->asc, floppy->ascq);
|
||||
} else
|
||||
printk(KERN_ERR "Error in REQUEST SENSE itself - "
|
||||
"Aborting request!\n");
|
||||
printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
|
||||
"Aborting request!\n");
|
||||
}
|
||||
|
||||
idefloppy_end_request(drive, uptodate, 0);
|
||||
}
|
||||
|
||||
void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
|
||||
{
|
||||
ide_init_pc(pc);
|
||||
pc->c[0] = GPCMD_REQUEST_SENSE;
|
||||
pc->c[4] = 255;
|
||||
pc->req_xfer = 18;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when an error was detected during the last packet command. We queue a
|
||||
* request sense packet command in the head of the request list.
|
||||
*/
|
||||
static void idefloppy_retry_pc(ide_drive_t *drive)
|
||||
{
|
||||
struct ide_floppy_obj *floppy = drive->driver_data;
|
||||
struct request *rq = &floppy->request_sense_rq;
|
||||
struct ide_atapi_pc *pc = &floppy->request_sense_pc;
|
||||
|
||||
(void)ide_read_error(drive);
|
||||
ide_floppy_create_request_sense_cmd(pc);
|
||||
ide_queue_pc_head(drive, floppy->disk, pc, rq);
|
||||
}
|
||||
|
||||
/* The usual interrupt handler called during a packet command. */
|
||||
static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
|
||||
return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr,
|
||||
WAIT_FLOPPY_CMD, NULL, idefloppy_update_buffers,
|
||||
idefloppy_retry_pc, NULL, ide_io_buffers);
|
||||
}
|
||||
|
||||
/*
|
||||
* What we have here is a classic case of a top half / bottom half interrupt
|
||||
* service routine. In interrupt mode, the device sends an interrupt to signal
|
||||
* that it is ready to receive a packet. However, we need to delay about 2-3
|
||||
* ticks before issuing the packet or we gets in trouble.
|
||||
*/
|
||||
static int idefloppy_transfer_pc(ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
|
||||
/* Send the actual packet */
|
||||
drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
|
||||
|
||||
/* Timeout for the packet command */
|
||||
return WAIT_FLOPPY_CMD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called as an interrupt (or directly). When the device says it's ready for a
|
||||
* packet, we schedule the packet transfer to occur about 2-3 ticks later in
|
||||
* transfer_pc.
|
||||
*/
|
||||
static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
struct ide_atapi_pc *pc = floppy->pc;
|
||||
ide_expiry_t *expiry;
|
||||
unsigned int timeout;
|
||||
|
||||
/*
|
||||
* The following delay solves a problem with ATAPI Zip 100 drives
|
||||
* where the Busy flag was apparently being deasserted before the
|
||||
* unit was ready to receive data. This was happening on a
|
||||
* 1200 MHz Athlon system. 10/26/01 25msec is too short,
|
||||
* 40 and 50msec work well. idefloppy_pc_intr will not be actually
|
||||
* used until after the packet is moved in about 50 msec.
|
||||
*/
|
||||
if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
|
||||
timeout = floppy->ticks;
|
||||
expiry = &idefloppy_transfer_pc;
|
||||
} else {
|
||||
timeout = WAIT_FLOPPY_CMD;
|
||||
expiry = NULL;
|
||||
}
|
||||
|
||||
return ide_transfer_pc(drive, pc, idefloppy_pc_intr, timeout, expiry);
|
||||
}
|
||||
|
||||
static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
|
||||
struct ide_atapi_pc *pc)
|
||||
{
|
||||
@ -283,7 +212,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
|
||||
floppy->ascq == 0x00)
|
||||
return;
|
||||
|
||||
printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
|
||||
printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
|
||||
"asc = %2x, ascq = %2x\n",
|
||||
floppy->drive->name, pc->c[0], floppy->sense_key,
|
||||
floppy->asc, floppy->ascq);
|
||||
@ -298,8 +227,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
|
||||
if (floppy->failed_pc == NULL &&
|
||||
pc->c[0] != GPCMD_REQUEST_SENSE)
|
||||
floppy->failed_pc = pc;
|
||||
|
||||
/* Set the current packet command */
|
||||
floppy->pc = pc;
|
||||
drive->pc = pc;
|
||||
|
||||
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
|
||||
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
|
||||
@ -308,16 +238,15 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
|
||||
pc->error = IDEFLOPPY_ERROR_GENERAL;
|
||||
|
||||
floppy->failed_pc = NULL;
|
||||
drive->pc_callback(drive);
|
||||
drive->pc_callback(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
debug_log("Retry number - %d\n", pc->retries);
|
||||
ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries);
|
||||
|
||||
pc->retries++;
|
||||
|
||||
return ide_issue_pc(drive, pc, idefloppy_start_pc_transfer,
|
||||
WAIT_FLOPPY_CMD, NULL);
|
||||
return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
|
||||
}
|
||||
|
||||
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
|
||||
@ -347,23 +276,23 @@ void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
|
||||
length += 32;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "ide-floppy: unsupported page code "
|
||||
"in create_mode_sense_cmd\n");
|
||||
printk(KERN_ERR PFX "unsupported page code in %s\n", __func__);
|
||||
}
|
||||
put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
|
||||
pc->req_xfer = length;
|
||||
}
|
||||
|
||||
static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
|
||||
static void idefloppy_create_rw_cmd(ide_drive_t *drive,
|
||||
struct ide_atapi_pc *pc, struct request *rq,
|
||||
unsigned long sector)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
int block = sector / floppy->bs_factor;
|
||||
int blocks = rq->nr_sectors / floppy->bs_factor;
|
||||
int cmd = rq_data_dir(rq);
|
||||
|
||||
debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
|
||||
block, blocks);
|
||||
ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__,
|
||||
block, blocks);
|
||||
|
||||
ide_init_pc(pc);
|
||||
pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
|
||||
@ -408,41 +337,42 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
|
||||
struct ide_atapi_pc *pc;
|
||||
unsigned long block = (unsigned long)block_s;
|
||||
|
||||
debug_log("%s: dev: %s, cmd: 0x%x, cmd_type: %x, errors: %d\n",
|
||||
__func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
|
||||
rq->cmd[0], rq->cmd_type, rq->errors);
|
||||
ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
|
||||
"errors: %d\n",
|
||||
__func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
|
||||
rq->cmd[0], rq->cmd_type, rq->errors);
|
||||
|
||||
debug_log("%s: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",
|
||||
__func__, (long)rq->sector, rq->nr_sectors,
|
||||
rq->current_nr_sectors);
|
||||
ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
|
||||
"current_nr_sectors: %d\n",
|
||||
__func__, (long)rq->sector, rq->nr_sectors,
|
||||
rq->current_nr_sectors);
|
||||
|
||||
if (rq->errors >= ERROR_MAX) {
|
||||
if (floppy->failed_pc)
|
||||
ide_floppy_report_error(floppy, floppy->failed_pc);
|
||||
else
|
||||
printk(KERN_ERR "ide-floppy: %s: I/O error\n",
|
||||
drive->name);
|
||||
printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
|
||||
|
||||
idefloppy_end_request(drive, 0, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
if (blk_fs_request(rq)) {
|
||||
if (((long)rq->sector % floppy->bs_factor) ||
|
||||
(rq->nr_sectors % floppy->bs_factor)) {
|
||||
printk(KERN_ERR "%s: unsupported r/w request size\n",
|
||||
drive->name);
|
||||
printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
|
||||
drive->name);
|
||||
idefloppy_end_request(drive, 0, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
pc = &floppy->queued_pc;
|
||||
idefloppy_create_rw_cmd(floppy, pc, rq, block);
|
||||
idefloppy_create_rw_cmd(drive, pc, rq, block);
|
||||
} else if (blk_special_request(rq)) {
|
||||
pc = (struct ide_atapi_pc *) rq->buffer;
|
||||
} else if (blk_pc_request(rq)) {
|
||||
pc = &floppy->queued_pc;
|
||||
idefloppy_blockpc_cmd(floppy, pc, rq);
|
||||
} else {
|
||||
blk_dump_rq_flags(rq,
|
||||
"ide-floppy: unsupported command in queue");
|
||||
blk_dump_rq_flags(rq, PFX "unsupported command in queue");
|
||||
idefloppy_end_request(drive, 0, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -475,8 +405,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
|
||||
ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
|
||||
|
||||
if (ide_queue_pc_tail(drive, disk, &pc)) {
|
||||
printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
|
||||
" parameters\n");
|
||||
printk(KERN_ERR PFX "Can't get flexible disk page params\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -499,7 +428,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
|
||||
capacity = cyls * heads * sectors * sector_size;
|
||||
|
||||
if (memcmp(page, &floppy->flexible_disk_page, 32))
|
||||
printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
|
||||
printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
|
||||
"%d sector size, %d rpm\n",
|
||||
drive->name, capacity / 1024, cyls, heads,
|
||||
sectors, transfer_rate / 8, sector_size, rpm);
|
||||
@ -511,7 +440,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
|
||||
lba_capacity = floppy->blocks * floppy->block_size;
|
||||
|
||||
if (capacity < lba_capacity) {
|
||||
printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
|
||||
printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
|
||||
"bytes, but the drive only handles %d\n",
|
||||
drive->name, lba_capacity, capacity);
|
||||
floppy->blocks = floppy->block_size ?
|
||||
@ -541,7 +470,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
|
||||
|
||||
ide_floppy_create_read_capacity_cmd(&pc);
|
||||
if (ide_queue_pc_tail(drive, disk, &pc)) {
|
||||
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
|
||||
printk(KERN_ERR PFX "Can't get floppy parameters\n");
|
||||
return 1;
|
||||
}
|
||||
header_len = pc.buf[3];
|
||||
@ -554,8 +483,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
|
||||
blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
|
||||
length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
|
||||
|
||||
debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
|
||||
i, blocks * length / 1024, blocks, length);
|
||||
ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
|
||||
"%d sector size\n",
|
||||
i, blocks * length / 1024, blocks, length);
|
||||
|
||||
if (i)
|
||||
continue;
|
||||
@ -575,23 +505,24 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
|
||||
case CAPACITY_CURRENT:
|
||||
/* Normal Zip/LS-120 disks */
|
||||
if (memcmp(cap_desc, &floppy->cap_desc, 8))
|
||||
printk(KERN_INFO "%s: %dkB, %d blocks, %d "
|
||||
"sector size\n", drive->name,
|
||||
blocks * length / 1024, blocks, length);
|
||||
printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
|
||||
"sector size\n",
|
||||
drive->name, blocks * length / 1024,
|
||||
blocks, length);
|
||||
memcpy(&floppy->cap_desc, cap_desc, 8);
|
||||
|
||||
if (!length || length % 512) {
|
||||
printk(KERN_NOTICE "%s: %d bytes block size "
|
||||
"not supported\n", drive->name, length);
|
||||
printk(KERN_NOTICE PFX "%s: %d bytes block size"
|
||||
" not supported\n", drive->name, length);
|
||||
} else {
|
||||
floppy->blocks = blocks;
|
||||
floppy->block_size = length;
|
||||
floppy->bs_factor = length / 512;
|
||||
if (floppy->bs_factor != 1)
|
||||
printk(KERN_NOTICE "%s: warning: non "
|
||||
"512 bytes block size not "
|
||||
"fully supported\n",
|
||||
drive->name);
|
||||
printk(KERN_NOTICE PFX "%s: Warning: "
|
||||
"non 512 bytes block size not "
|
||||
"fully supported\n",
|
||||
drive->name);
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
@ -600,15 +531,16 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
|
||||
* This is a KERN_ERR so it appears on screen
|
||||
* for the user to see
|
||||
*/
|
||||
printk(KERN_ERR "%s: No disk in drive\n", drive->name);
|
||||
printk(KERN_ERR PFX "%s: No disk in drive\n",
|
||||
drive->name);
|
||||
break;
|
||||
case CAPACITY_INVALID:
|
||||
printk(KERN_ERR "%s: Invalid capacity for disk "
|
||||
printk(KERN_ERR PFX "%s: Invalid capacity for disk "
|
||||
"in drive\n", drive->name);
|
||||
break;
|
||||
}
|
||||
debug_log("Descriptor 0 Code: %d\n",
|
||||
pc.buf[desc_start + 4] & 0x03);
|
||||
ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n",
|
||||
pc.buf[desc_start + 4] & 0x03);
|
||||
}
|
||||
|
||||
/* Clik! disk does not support get_flexible_disk_page */
|
||||
@ -620,7 +552,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static sector_t idefloppy_capacity(ide_drive_t *drive)
|
||||
sector_t ide_floppy_capacity(ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
unsigned long capacity = floppy->blocks * floppy->bs_factor;
|
||||
@ -628,46 +560,14 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
|
||||
return capacity;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
|
||||
static int get_ticks(ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
return floppy->ticks;
|
||||
}
|
||||
|
||||
static int set_ticks(ide_drive_t *drive, int arg)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
floppy->ticks = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IDE_DEVSET(ticks, DS_SYNC, get_ticks, set_ticks);
|
||||
|
||||
static const struct ide_proc_devset idefloppy_settings[] = {
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 1023),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(ticks, 0, 255),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
|
||||
{
|
||||
u16 *id = drive->id;
|
||||
u8 gcw[2];
|
||||
|
||||
*((u16 *)&gcw) = id[ATA_ID_CONFIG];
|
||||
drive->pc_callback = ide_floppy_callback;
|
||||
drive->pc_update_buffers = idefloppy_update_buffers;
|
||||
drive->pc_io_buffers = ide_io_buffers;
|
||||
|
||||
drive->pc_callback = ide_floppy_callback;
|
||||
|
||||
if (((gcw[0] & 0x60) >> 5) == 1)
|
||||
drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
|
||||
/*
|
||||
* We used to check revisions here. At this point however I'm giving up.
|
||||
* Just assume they are all broken, its easier.
|
||||
@ -680,7 +580,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
|
||||
if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
|
||||
drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
|
||||
/* This value will be visible in the /proc/ide/hdx/settings */
|
||||
floppy->ticks = IDEFLOPPY_TICKS_DELAY;
|
||||
drive->pc_delay = IDEFLOPPY_PC_DELAY;
|
||||
blk_queue_max_sectors(drive->queue, 64);
|
||||
}
|
||||
|
||||
@ -714,7 +614,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
|
||||
|
||||
static void idefloppy_cleanup_obj(struct kref *kref)
|
||||
{
|
||||
struct ide_floppy_obj *floppy = to_ide_floppy(kref);
|
||||
struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
struct gendisk *g = floppy->disk;
|
||||
|
||||
@ -724,24 +624,6 @@ static void idefloppy_cleanup_obj(struct kref *kref)
|
||||
kfree(floppy);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDE_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 }
|
||||
};
|
||||
#endif /* CONFIG_IDE_PROC_FS */
|
||||
|
||||
static int ide_floppy_probe(ide_drive_t *);
|
||||
|
||||
static ide_driver_t idefloppy_driver = {
|
||||
@ -753,13 +635,12 @@ static ide_driver_t idefloppy_driver = {
|
||||
.probe = ide_floppy_probe,
|
||||
.remove = ide_floppy_remove,
|
||||
.version = IDEFLOPPY_VERSION,
|
||||
.media = ide_floppy,
|
||||
.do_request = idefloppy_do_request,
|
||||
.end_request = idefloppy_end_request,
|
||||
.error = __ide_error,
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
.proc = idefloppy_proc,
|
||||
.settings = idefloppy_settings,
|
||||
.proc = ide_floppy_proc,
|
||||
.settings = ide_floppy_settings,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -770,14 +651,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
|
||||
ide_drive_t *drive;
|
||||
int ret = 0;
|
||||
|
||||
debug_log("Reached %s\n", __func__);
|
||||
|
||||
floppy = ide_floppy_get(disk);
|
||||
if (!floppy)
|
||||
return -ENXIO;
|
||||
|
||||
drive = floppy->drive;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
floppy->openers++;
|
||||
|
||||
if (floppy->openers == 1) {
|
||||
@ -822,10 +703,10 @@ out_put_floppy:
|
||||
static int idefloppy_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
|
||||
struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
|
||||
debug_log("Reached %s\n", __func__);
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (floppy->openers == 1) {
|
||||
ide_set_media_lock(drive, disk, 0);
|
||||
@ -841,7 +722,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
|
||||
|
||||
static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
{
|
||||
struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
|
||||
struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
|
||||
ide_floppy_obj);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
|
||||
geo->heads = drive->bios_head;
|
||||
@ -850,64 +732,15 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
unsigned long arg, unsigned int cmd)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
struct gendisk *disk = floppy->disk;
|
||||
int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
|
||||
|
||||
if (floppy->openers > 1)
|
||||
return -EBUSY;
|
||||
|
||||
ide_set_media_lock(drive, disk, prevent);
|
||||
|
||||
if (cmd == CDROMEJECT)
|
||||
ide_do_start_stop(drive, disk, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int idefloppy_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
struct ide_atapi_pc pc;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int err;
|
||||
|
||||
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
|
||||
return ide_floppy_lockdoor(drive, &pc, arg, cmd);
|
||||
|
||||
err = ide_floppy_format_ioctl(drive, file, cmd, argp);
|
||||
if (err != -ENOTTY)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* skip SCSI_IOCTL_SEND_COMMAND (deprecated)
|
||||
* and CDROM_SEND_PACKET (legacy) ioctls
|
||||
*/
|
||||
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
|
||||
err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
|
||||
bdev->bd_disk, cmd, argp);
|
||||
|
||||
if (err == -ENOTTY)
|
||||
err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int idefloppy_media_changed(struct gendisk *disk)
|
||||
{
|
||||
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
|
||||
struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
int ret;
|
||||
|
||||
/* do not scan partitions twice if this is a removable device */
|
||||
if (drive->attach) {
|
||||
drive->attach = 0;
|
||||
if (drive->dev_flags & IDE_DFLAG_ATTACH) {
|
||||
drive->dev_flags &= ~IDE_DFLAG_ATTACH;
|
||||
return 0;
|
||||
}
|
||||
ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
|
||||
@ -917,8 +750,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
|
||||
|
||||
static int idefloppy_revalidate_disk(struct gendisk *disk)
|
||||
{
|
||||
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
|
||||
set_capacity(disk, idefloppy_capacity(floppy->drive));
|
||||
struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
|
||||
set_capacity(disk, ide_floppy_capacity(floppy->drive));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -926,7 +759,7 @@ static struct block_device_operations idefloppy_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = idefloppy_open,
|
||||
.release = idefloppy_release,
|
||||
.ioctl = idefloppy_ioctl,
|
||||
.ioctl = ide_floppy_ioctl,
|
||||
.getgeo = idefloppy_getgeo,
|
||||
.media_changed = idefloppy_media_changed,
|
||||
.revalidate_disk = idefloppy_revalidate_disk
|
||||
@ -944,14 +777,14 @@ static int ide_floppy_probe(ide_drive_t *drive)
|
||||
goto failed;
|
||||
|
||||
if (!ide_check_atapi_device(drive, DRV_NAME)) {
|
||||
printk(KERN_ERR "ide-floppy: %s: not supported by this version"
|
||||
" of ide-floppy\n", drive->name);
|
||||
printk(KERN_ERR PFX "%s: not supported by this version of "
|
||||
DRV_NAME "\n", drive->name);
|
||||
goto failed;
|
||||
}
|
||||
floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
|
||||
if (!floppy) {
|
||||
printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
|
||||
" structure\n", drive->name);
|
||||
printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
|
||||
drive->name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -971,13 +804,16 @@ static int ide_floppy_probe(ide_drive_t *drive)
|
||||
|
||||
drive->driver_data = floppy;
|
||||
|
||||
drive->debug_mask = debug_mask;
|
||||
|
||||
idefloppy_setup(drive, floppy);
|
||||
drive->dev_flags |= IDE_DFLAG_ATTACH;
|
||||
|
||||
g->minors = 1 << PARTN_BITS;
|
||||
g->driverfs_dev = &drive->gendev;
|
||||
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
|
||||
if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
|
||||
g->flags = GENHD_FL_REMOVABLE;
|
||||
g->fops = &idefloppy_ops;
|
||||
drive->attach = 1;
|
||||
add_disk(g);
|
||||
return 0;
|
||||
|
||||
@ -994,7 +830,7 @@ static void __exit idefloppy_exit(void)
|
||||
|
||||
static int __init idefloppy_init(void)
|
||||
{
|
||||
printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
|
||||
printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
|
||||
return driver_register(&idefloppy_driver.gen_driver);
|
||||
}
|
||||
|
||||
|
@ -13,20 +13,14 @@ typedef struct ide_floppy_obj {
|
||||
struct kref kref;
|
||||
unsigned int openers; /* protected by BKL for now */
|
||||
|
||||
/* Current packet command */
|
||||
struct ide_atapi_pc *pc;
|
||||
/* Last failed packet command */
|
||||
struct ide_atapi_pc *failed_pc;
|
||||
/* used for blk_{fs,pc}_request() requests */
|
||||
struct ide_atapi_pc queued_pc;
|
||||
|
||||
struct ide_atapi_pc request_sense_pc;
|
||||
struct request request_sense_rq;
|
||||
|
||||
/* Last error information */
|
||||
u8 sense_key, asc, ascq;
|
||||
/* delay this long before sending packet command */
|
||||
u8 ticks;
|
||||
|
||||
int progress_indication;
|
||||
|
||||
/* Device information */
|
||||
@ -54,10 +48,15 @@ typedef struct ide_floppy_obj {
|
||||
/* ide-floppy.c */
|
||||
void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
|
||||
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
|
||||
void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *);
|
||||
sector_t ide_floppy_capacity(ide_drive_t *);
|
||||
|
||||
/* ide-floppy_ioctl.c */
|
||||
int ide_floppy_format_ioctl(ide_drive_t *, struct file *, unsigned int,
|
||||
void __user *);
|
||||
int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
/* ide-floppy_proc.c */
|
||||
extern ide_proc_entry_t ide_floppy_proc[];
|
||||
extern const struct ide_proc_devset ide_floppy_settings[];
|
||||
#endif
|
||||
|
||||
#endif /*__IDE_FLOPPY_H */
|
||||
|
@ -195,7 +195,7 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
|
||||
int progress_indication = 0x10000;
|
||||
|
||||
if (drive->atapi_flags & IDE_AFLAG_SRFP) {
|
||||
ide_floppy_create_request_sense_cmd(&pc);
|
||||
ide_create_request_sense_cmd(drive, &pc);
|
||||
if (ide_queue_pc_tail(drive, floppy->disk, &pc))
|
||||
return -EIO;
|
||||
|
||||
@ -223,8 +223,26 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
|
||||
unsigned int cmd, void __user *argp)
|
||||
static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
unsigned long arg, unsigned int cmd)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
struct gendisk *disk = floppy->disk;
|
||||
int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
|
||||
|
||||
if (floppy->openers > 1)
|
||||
return -EBUSY;
|
||||
|
||||
ide_set_media_lock(drive, disk, prevent);
|
||||
|
||||
if (cmd == CDROMEJECT)
|
||||
ide_do_start_stop(drive, disk, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
|
||||
unsigned int cmd, void __user *argp)
|
||||
{
|
||||
switch (cmd) {
|
||||
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
|
||||
@ -241,3 +259,35 @@ int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
int ide_floppy_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
|
||||
ide_floppy_obj);
|
||||
ide_drive_t *drive = floppy->drive;
|
||||
struct ide_atapi_pc pc;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int err;
|
||||
|
||||
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
|
||||
return ide_floppy_lockdoor(drive, &pc, arg, cmd);
|
||||
|
||||
err = ide_floppy_format_ioctl(drive, file, cmd, argp);
|
||||
if (err != -ENOTTY)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* skip SCSI_IOCTL_SEND_COMMAND (deprecated)
|
||||
* and CDROM_SEND_PACKET (legacy) ioctls
|
||||
*/
|
||||
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
|
||||
err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
|
||||
bdev->bd_disk, cmd, argp);
|
||||
|
||||
if (err == -ENOTTY)
|
||||
err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
33
drivers/ide/ide-floppy_proc.c
Normal file
33
drivers/ide/ide-floppy_proc.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
|
||||
#include "ide-floppy.h"
|
||||
|
||||
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)ide_floppy_capacity(drive));
|
||||
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
|
||||
}
|
||||
|
||||
ide_proc_entry_t ide_floppy_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 }
|
||||
};
|
||||
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
ide_devset_rw_field(ticks, pc_delay);
|
||||
|
||||
const struct ide_proc_devset ide_floppy_settings[] = {
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 1023),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(ticks, 0, 255),
|
||||
{ 0 },
|
||||
};
|
@ -137,15 +137,10 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary)
|
||||
|
||||
static int __init ide_generic_init(void)
|
||||
{
|
||||
hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
|
||||
struct ide_host *host;
|
||||
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
|
||||
unsigned long io_addr;
|
||||
int i, rc, primary = 0, secondary = 0;
|
||||
int i, rc = 0, primary = 0, secondary = 0;
|
||||
|
||||
#ifdef CONFIG_MIPS
|
||||
if (!ide_probe_legacy())
|
||||
return -ENODEV;
|
||||
#endif
|
||||
ide_generic_check_pci_legacy_iobases(&primary, &secondary);
|
||||
|
||||
if (!probe_mask) {
|
||||
@ -161,13 +156,9 @@ static int __init ide_generic_init(void)
|
||||
printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports "
|
||||
"upon user request\n");
|
||||
|
||||
memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
|
||||
io_addr = legacy_bases[i];
|
||||
|
||||
hws[i] = NULL;
|
||||
|
||||
if ((probe_mask & (1 << i)) && io_addr) {
|
||||
if (!request_region(io_addr, 8, DRV_NAME)) {
|
||||
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX "
|
||||
@ -184,45 +175,27 @@ static int __init ide_generic_init(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&hw[i], 0, sizeof(hw[i]));
|
||||
ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
|
||||
memset(&hw, 0, sizeof(hw));
|
||||
ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
|
||||
#ifdef CONFIG_IA64
|
||||
hw[i].irq = isa_irq_to_vector(legacy_irqs[i]);
|
||||
hw.irq = isa_irq_to_vector(legacy_irqs[i]);
|
||||
#else
|
||||
hw[i].irq = legacy_irqs[i];
|
||||
hw.irq = legacy_irqs[i];
|
||||
#endif
|
||||
hw[i].chipset = ide_generic;
|
||||
hw.chipset = ide_generic;
|
||||
|
||||
hws[i] = &hw[i];
|
||||
rc = ide_host_add(NULL, hws, NULL);
|
||||
if (rc) {
|
||||
release_region(io_addr + 0x206, 1);
|
||||
release_region(io_addr, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
host = ide_host_alloc_all(NULL, hws);
|
||||
if (host == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = ide_host_register(host, NULL, hws);
|
||||
if (rc)
|
||||
goto err_free;
|
||||
|
||||
if (ide_generic_sysfs_init())
|
||||
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
|
||||
"class\n");
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
ide_host_free(host);
|
||||
err:
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
if (hws[i] == NULL)
|
||||
continue;
|
||||
|
||||
io_addr = hws[i]->io_ports.data_addr;
|
||||
release_region(io_addr + 0x206, 1);
|
||||
release_region(io_addr, 8);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,9 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
|
||||
* decide whether to reenable DMA -- 3 is a random magic for now,
|
||||
* if we DMA timeout more than 3 times, just stay in PIO
|
||||
*/
|
||||
if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
|
||||
drive->state = 0;
|
||||
if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
|
||||
drive->retry_pio <= 3) {
|
||||
drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
|
||||
@ -131,21 +132,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
|
||||
}
|
||||
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_restore_pio = ide_pm_state_start_resume,
|
||||
idedisk_pm_idle,
|
||||
ide_pm_restore_dma,
|
||||
};
|
||||
|
||||
static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
@ -154,20 +140,20 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
|
||||
return;
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
|
||||
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
|
||||
if (pm->pm_state == PM_EVENT_FREEZE)
|
||||
pm->pm_step = ide_pm_state_completed;
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
else
|
||||
pm->pm_step = idedisk_pm_standby;
|
||||
pm->pm_step = IDE_PM_STANDBY;
|
||||
break;
|
||||
case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
|
||||
pm->pm_step = ide_pm_state_completed;
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
break;
|
||||
case idedisk_pm_restore_pio: /* Resume step 1 complete */
|
||||
pm->pm_step = idedisk_pm_idle;
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
pm->pm_step = IDE_PM_IDLE;
|
||||
break;
|
||||
case idedisk_pm_idle: /* Resume step 2 (idle) complete */
|
||||
pm->pm_step = ide_pm_restore_dma;
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle)*/
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -180,11 +166,12 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
||||
memset(args, 0, sizeof(*args));
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */
|
||||
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 || ata_id_flush_enabled(drive->id) == 0) {
|
||||
if (ata_id_flush_enabled(drive->id) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
|
||||
ide_complete_power_step(drive, rq, 0, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -193,27 +180,23 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
||||
else
|
||||
args->tf.command = ATA_CMD_FLUSH;
|
||||
goto out_do_tf;
|
||||
|
||||
case idedisk_pm_standby: /* Suspend step 2 (standby) */
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
args->tf.command = ATA_CMD_STANDBYNOW1;
|
||||
goto out_do_tf;
|
||||
|
||||
case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
ide_set_max_pio(drive);
|
||||
/*
|
||||
* skip idedisk_pm_idle for ATAPI devices
|
||||
* skip IDE_PM_IDLE for ATAPI devices
|
||||
*/
|
||||
if (drive->media != ide_disk)
|
||||
pm->pm_step = ide_pm_restore_dma;
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
else
|
||||
ide_complete_power_step(drive, rq, 0, 0);
|
||||
return ide_stopped;
|
||||
|
||||
case idedisk_pm_idle: /* Resume step 2 (idle) */
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle) */
|
||||
args->tf.command = ATA_CMD_IDLEIMMEDIATE;
|
||||
goto out_do_tf;
|
||||
|
||||
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
|
||||
case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
|
||||
/*
|
||||
* Right now, all we do is call ide_set_dma(drive),
|
||||
* we could be smarter and check for current xfer_speed
|
||||
@ -222,12 +205,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
||||
if (drive->hwif->dma_ops == NULL)
|
||||
break;
|
||||
/*
|
||||
* TODO: respect ->using_dma setting
|
||||
* TODO: respect IDE_DFLAG_USING_DMA
|
||||
*/
|
||||
ide_set_dma(drive);
|
||||
break;
|
||||
}
|
||||
pm->pm_step = ide_pm_state_completed;
|
||||
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
return ide_stopped;
|
||||
|
||||
out_do_tf:
|
||||
@ -287,7 +271,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
|
||||
if (blk_pm_suspend_request(rq)) {
|
||||
blk_stop_queue(drive->queue);
|
||||
} else {
|
||||
drive->blocked = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
|
||||
blk_start_queue(drive->queue);
|
||||
}
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
@ -343,7 +327,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
|
||||
drive->name, rq->pm->pm_step, stat, err);
|
||||
#endif
|
||||
ide_complete_power_step(drive, rq, stat, err);
|
||||
if (pm->pm_step == ide_pm_state_completed)
|
||||
if (pm->pm_step == IDE_PM_COMPLETED)
|
||||
ide_complete_pm_request(drive, rq);
|
||||
return;
|
||||
}
|
||||
@ -374,13 +358,14 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
|
||||
if ((stat & ATA_BUSY) ||
|
||||
((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
|
||||
/* other bits are useless when BUSY */
|
||||
rq->errors |= ERROR_RESET;
|
||||
} else if (stat & ATA_ERR) {
|
||||
/* err has different meaning on cdrom and tape */
|
||||
if (err == ATA_ABORTED) {
|
||||
if (drive->select.b.lba &&
|
||||
if ((drive->dev_flags & IDE_DFLAG_LBA) &&
|
||||
/* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
|
||||
hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
|
||||
return ide_stopped;
|
||||
@ -428,7 +413,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
|
||||
if ((stat & ATA_BUSY) ||
|
||||
((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
|
||||
/* other bits are useless when BUSY */
|
||||
rq->errors |= ERROR_RESET;
|
||||
} else {
|
||||
@ -509,7 +495,7 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
|
||||
tf->lbal = drive->sect;
|
||||
tf->lbam = drive->cyl;
|
||||
tf->lbah = drive->cyl >> 8;
|
||||
tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
|
||||
tf->device = (drive->head - 1) | drive->select;
|
||||
tf->command = ATA_CMD_INIT_DEV_PARAMS;
|
||||
}
|
||||
|
||||
@ -557,30 +543,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
|
||||
*/
|
||||
static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
|
||||
{
|
||||
switch (req_pio) {
|
||||
case 202:
|
||||
case 201:
|
||||
case 200:
|
||||
case 102:
|
||||
case 101:
|
||||
case 100:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
|
||||
case 9:
|
||||
case 8:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
|
||||
case 7:
|
||||
case 6:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* do_special - issue some special commands
|
||||
* @drive: drive the command is for
|
||||
@ -598,45 +560,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
|
||||
#ifdef DEBUG
|
||||
printk("%s: do_special: 0x%02x\n", drive->name, s->all);
|
||||
#endif
|
||||
if (s->b.set_tune) {
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
const struct ide_port_ops *port_ops = hwif->port_ops;
|
||||
u8 req_pio = drive->tune_req;
|
||||
if (drive->media == ide_disk)
|
||||
return ide_disk_special(drive);
|
||||
|
||||
s->b.set_tune = 0;
|
||||
|
||||
if (set_pio_mode_abuse(drive->hwif, req_pio)) {
|
||||
/*
|
||||
* take ide_lock for drive->[no_]unmask/[no_]io_32bit
|
||||
*/
|
||||
if (req_pio == 8 || req_pio == 9) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
port_ops->set_pio_mode(drive, req_pio);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
} else
|
||||
port_ops->set_pio_mode(drive, req_pio);
|
||||
} else {
|
||||
int keep_dma = drive->using_dma;
|
||||
|
||||
ide_set_pio(drive, req_pio);
|
||||
|
||||
if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
|
||||
if (keep_dma)
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
}
|
||||
|
||||
return ide_stopped;
|
||||
} else {
|
||||
if (drive->media == ide_disk)
|
||||
return ide_disk_special(drive);
|
||||
|
||||
s->all = 0;
|
||||
drive->mult_req = 0;
|
||||
return ide_stopped;
|
||||
}
|
||||
s->all = 0;
|
||||
drive->mult_req = 0;
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
void ide_map_sg(ide_drive_t *drive, struct request *rq)
|
||||
@ -726,10 +655,7 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
|
||||
if (!(setting->flags & DS_SYNC))
|
||||
return setting->set(drive, arg);
|
||||
|
||||
rq = blk_get_request(q, READ, GFP_KERNEL);
|
||||
if (!rq)
|
||||
return -ENOMEM;
|
||||
|
||||
rq = blk_get_request(q, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_SPECIAL;
|
||||
rq->cmd_len = 5;
|
||||
rq->cmd[0] = REQ_DEVSET_EXEC;
|
||||
@ -746,7 +672,32 @@ EXPORT_SYMBOL_GPL(ide_devset_execute);
|
||||
|
||||
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
switch (rq->cmd[0]) {
|
||||
u8 cmd = rq->cmd[0];
|
||||
|
||||
if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
|
||||
ide_task_t task;
|
||||
struct ide_taskfile *tf = &task.tf;
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
if (cmd == REQ_PARK_HEADS) {
|
||||
drive->sleep = *(unsigned long *)rq->special;
|
||||
drive->dev_flags |= IDE_DFLAG_SLEEPING;
|
||||
tf->command = ATA_CMD_IDLEIMMEDIATE;
|
||||
tf->feature = 0x44;
|
||||
tf->lbal = 0x4c;
|
||||
tf->lbam = 0x4e;
|
||||
tf->lbah = 0x55;
|
||||
task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
|
||||
} else /* cmd == REQ_UNPARK_HEADS */
|
||||
tf->command = ATA_CMD_CHK_POWER;
|
||||
|
||||
task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
task.rq = rq;
|
||||
drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
|
||||
return do_rw_taskfile(drive, &task);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case REQ_DEVSET_EXEC:
|
||||
{
|
||||
int err, (*setfunc)(ide_drive_t *, int) = rq->special;
|
||||
@ -773,11 +724,11 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
||||
if (blk_pm_suspend_request(rq) &&
|
||||
pm->pm_step == ide_pm_state_start_suspend)
|
||||
pm->pm_step == IDE_PM_START_SUSPEND)
|
||||
/* Mark drive blocked when starting the suspend sequence. */
|
||||
drive->blocked = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_BLOCKED;
|
||||
else if (blk_pm_resume_request(rq) &&
|
||||
pm->pm_step == ide_pm_state_start_resume) {
|
||||
pm->pm_step == IDE_PM_START_RESUME) {
|
||||
/*
|
||||
* The first thing we do on wakeup is to wait for BSY bit to
|
||||
* go away (with a looong timeout) as a drive on this hwif may
|
||||
@ -857,7 +808,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
|
||||
#endif
|
||||
startstop = ide_start_power_step(drive, rq);
|
||||
if (startstop == ide_stopped &&
|
||||
pm->pm_step == ide_pm_state_completed)
|
||||
pm->pm_step == IDE_PM_COMPLETED)
|
||||
ide_complete_pm_request(drive, rq);
|
||||
return startstop;
|
||||
} else if (!rq->rq_disk && blk_special_request(rq))
|
||||
@ -895,7 +846,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
|
||||
if (timeout > WAIT_WORSTCASE)
|
||||
timeout = WAIT_WORSTCASE;
|
||||
drive->sleep = timeout + jiffies;
|
||||
drive->sleeping = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_SLEEPING;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_stall_queue);
|
||||
@ -935,18 +886,23 @@ repeat:
|
||||
}
|
||||
|
||||
do {
|
||||
if ((!drive->sleeping || time_after_eq(jiffies, drive->sleep))
|
||||
&& !elv_queue_empty(drive->queue)) {
|
||||
if (!best
|
||||
|| (drive->sleeping && (!best->sleeping || time_before(drive->sleep, best->sleep)))
|
||||
|| (!best->sleeping && time_before(WAKEUP(drive), WAKEUP(best))))
|
||||
{
|
||||
u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
|
||||
u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
|
||||
|
||||
if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
|
||||
!elv_queue_empty(drive->queue)) {
|
||||
if (best == NULL ||
|
||||
(dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
|
||||
(best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
|
||||
if (!blk_queue_plugged(drive->queue))
|
||||
best = drive;
|
||||
}
|
||||
}
|
||||
} while ((drive = drive->next) != hwgroup->drive);
|
||||
if (best && best->nice1 && !best->sleeping && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
|
||||
|
||||
if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
|
||||
(best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
|
||||
best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
|
||||
long t = (signed long)(WAKEUP(best) - jiffies);
|
||||
if (t >= WAIT_MIN_SLEEP) {
|
||||
/*
|
||||
@ -955,7 +911,7 @@ repeat:
|
||||
*/
|
||||
drive = best->next;
|
||||
do {
|
||||
if (!drive->sleeping
|
||||
if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
|
||||
&& time_before(jiffies - best->service_time, WAKEUP(drive))
|
||||
&& time_before(WAKEUP(drive), jiffies + t))
|
||||
{
|
||||
@ -1026,7 +982,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
hwgroup->rq = NULL;
|
||||
drive = hwgroup->drive;
|
||||
do {
|
||||
if (drive->sleeping && (!sleeping || time_before(drive->sleep, sleep))) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
|
||||
(sleeping == 0 ||
|
||||
time_before(drive->sleep, sleep))) {
|
||||
sleeping = 1;
|
||||
sleep = drive->sleep;
|
||||
}
|
||||
@ -1075,7 +1033,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
}
|
||||
hwgroup->hwif = hwif;
|
||||
hwgroup->drive = drive;
|
||||
drive->sleeping = 0;
|
||||
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
|
||||
drive->service_start = jiffies;
|
||||
|
||||
if (blk_queue_plugged(drive->queue)) {
|
||||
@ -1109,7 +1067,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
* We count how many times we loop here to make sure we service
|
||||
* all drives in the hwgroup without looping for ever
|
||||
*/
|
||||
if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
|
||||
blk_pm_request(rq) == 0 &&
|
||||
(rq->cmd_flags & REQ_PREEMPT) == 0) {
|
||||
drive = drive->next ? drive->next : hwgroup->drive;
|
||||
if (loops++ < 4 && !blk_queue_plugged(drive->queue))
|
||||
goto again;
|
||||
@ -1182,8 +1142,8 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
|
||||
* a timeout -- we'll reenable after we finish this next request
|
||||
* (or rather the first chunk of it) in pio.
|
||||
*/
|
||||
drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
|
||||
drive->retry_pio++;
|
||||
drive->state = DMA_PIO_RETRY;
|
||||
ide_dma_off_quietly(drive);
|
||||
|
||||
/*
|
||||
@ -1480,23 +1440,16 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
del_timer(&hwgroup->timer);
|
||||
spin_unlock(&ide_lock);
|
||||
|
||||
/* Some controllers might set DMA INTR no matter DMA or PIO;
|
||||
* bmdma status might need to be cleared even for
|
||||
* PIO interrupts to prevent spurious/lost irq.
|
||||
*/
|
||||
if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
|
||||
/* ide_dma_end() needs bmdma status for error checking.
|
||||
* So, skip clearing bmdma status here and leave it
|
||||
* to ide_dma_end() if this is dma interrupt.
|
||||
*/
|
||||
hwif->ide_dma_clear_irq(drive);
|
||||
if (hwif->port_ops && hwif->port_ops->clear_irq)
|
||||
hwif->port_ops->clear_irq(drive);
|
||||
|
||||
if (drive->unmask)
|
||||
if (drive->dev_flags & IDE_DFLAG_UNMASK)
|
||||
local_irq_enable_in_hardirq();
|
||||
|
||||
/* service this interrupt, may set handler for next interrupt */
|
||||
startstop = handler(drive);
|
||||
spin_lock_irq(&ide_lock);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
/*
|
||||
* Note that handler() may have set things up for another
|
||||
* interrupt to occur soon, but it cannot happen until
|
||||
|
@ -62,7 +62,7 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
|
||||
int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
|
||||
int rc = 0;
|
||||
|
||||
if (drive->id_read == 0) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
|
||||
rc = -ENOMSG;
|
||||
goto out;
|
||||
}
|
||||
@ -86,8 +86,10 @@ out:
|
||||
|
||||
static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
|
||||
{
|
||||
return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) |
|
||||
(drive->nice1 << IDE_NICE_1), (long __user *)arg);
|
||||
return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
|
||||
<< IDE_NICE_DSC_OVERLAP) |
|
||||
(!!(drive->dev_flags & IDE_DFLAG_NICE1)
|
||||
<< IDE_NICE_1), (long __user *)arg);
|
||||
}
|
||||
|
||||
static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
|
||||
@ -97,11 +99,18 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
|
||||
|
||||
if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
|
||||
(drive->media == ide_disk || drive->media == ide_floppy ||
|
||||
drive->scsi))
|
||||
(drive->dev_flags & IDE_DFLAG_SCSI)))
|
||||
return -EPERM;
|
||||
|
||||
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
|
||||
drive->nice1 = (arg >> IDE_NICE_1) & 1;
|
||||
if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
|
||||
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
|
||||
if ((arg >> IDE_NICE_1) & 1)
|
||||
drive->dev_flags |= IDE_DFLAG_NICE1;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_NICE1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
|
||||
tf_outb(tf->lbah, io_ports->lbah_addr);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
|
||||
tf_outb((tf->device & HIHI) | drive->select.all,
|
||||
tf_outb((tf->device & HIHI) | drive->select,
|
||||
io_ports->device_addr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_tf_load);
|
||||
@ -647,7 +647,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
|
||||
return 1;
|
||||
|
||||
no_80w:
|
||||
if (drive->udma33_warned == 1)
|
||||
if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
|
||||
return 0;
|
||||
|
||||
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
|
||||
@ -655,7 +655,7 @@ no_80w:
|
||||
drive->name,
|
||||
hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
|
||||
|
||||
drive->udma33_warned = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -711,7 +711,7 @@ int ide_driveid_update(ide_drive_t *drive)
|
||||
|
||||
kfree(id);
|
||||
|
||||
if (drive->using_dma && ide_id_dma_bug(drive))
|
||||
if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
|
||||
ide_dma_off(drive);
|
||||
|
||||
return 1;
|
||||
@ -790,7 +790,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
|
||||
|
||||
skip:
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA
|
||||
if (speed >= XFER_SW_DMA_0 && drive->using_dma)
|
||||
if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
|
||||
hwif->dma_ops->dma_host_set(drive, 1);
|
||||
else if (hwif->dma_ops) /* check if host supports DMA */
|
||||
ide_dma_off_quietly(drive);
|
||||
@ -940,6 +940,25 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
|
||||
{
|
||||
static const char *err_master_vals[] =
|
||||
{ NULL, "passed", "formatter device error",
|
||||
"sector buffer error", "ECC circuitry error",
|
||||
"controlling MPU error" };
|
||||
|
||||
u8 err_master = err & 0x7f;
|
||||
|
||||
printk(KERN_ERR "%s: reset: master: ", hwif->name);
|
||||
if (err_master && err_master < 6)
|
||||
printk(KERN_CONT "%s", err_master_vals[err_master]);
|
||||
else
|
||||
printk(KERN_CONT "error (0x%02x?)", err);
|
||||
if (err & 0x80)
|
||||
printk(KERN_CONT "; slave: failed");
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* reset_pollfunc() gets invoked to poll the interface for completion every 50ms
|
||||
* during an ide reset operation. If the drives have not yet responded,
|
||||
@ -975,31 +994,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
|
||||
drive->failures++;
|
||||
err = -EIO;
|
||||
} else {
|
||||
printk("%s: reset: ", hwif->name);
|
||||
tmp = ide_read_error(drive);
|
||||
|
||||
if (tmp == 1) {
|
||||
printk("success\n");
|
||||
printk(KERN_INFO "%s: reset: success\n", hwif->name);
|
||||
drive->failures = 0;
|
||||
} else {
|
||||
ide_reset_report_error(hwif, tmp);
|
||||
drive->failures++;
|
||||
printk("master: ");
|
||||
switch (tmp & 0x7f) {
|
||||
case 1: printk("passed");
|
||||
break;
|
||||
case 2: printk("formatter device error");
|
||||
break;
|
||||
case 3: printk("sector buffer error");
|
||||
break;
|
||||
case 4: printk("ECC circuitry error");
|
||||
break;
|
||||
case 5: printk("controlling MPU error");
|
||||
break;
|
||||
default:printk("error (0x%02x?)", tmp);
|
||||
}
|
||||
if (tmp & 0x80)
|
||||
printk("; slave: failed");
|
||||
printk("\n");
|
||||
err = -EIO;
|
||||
}
|
||||
}
|
||||
@ -1016,9 +1018,14 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
|
||||
drive->special.all = 0;
|
||||
drive->special.b.set_geometry = legacy;
|
||||
drive->special.b.recalibrate = legacy;
|
||||
|
||||
drive->mult_count = 0;
|
||||
if (!drive->keep_settings && !drive->using_dma)
|
||||
drive->dev_flags &= ~IDE_DFLAG_PARKED;
|
||||
|
||||
if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
|
||||
(drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
|
||||
drive->mult_req = 0;
|
||||
|
||||
if (drive->mult_req != drive->mult_count)
|
||||
drive->special.b.set_multmode = 1;
|
||||
}
|
||||
@ -1030,18 +1037,18 @@ static void pre_reset(ide_drive_t *drive)
|
||||
if (drive->media == ide_disk)
|
||||
ide_disk_pre_reset(drive);
|
||||
else
|
||||
drive->post_reset = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_POST_RESET;
|
||||
|
||||
if (drive->using_dma) {
|
||||
if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
|
||||
if (drive->crc_count)
|
||||
ide_check_dma_crc(drive);
|
||||
else
|
||||
ide_dma_off(drive);
|
||||
}
|
||||
|
||||
if (!drive->keep_settings) {
|
||||
if (!drive->using_dma) {
|
||||
drive->unmask = 0;
|
||||
if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
|
||||
drive->dev_flags &= ~IDE_DFLAG_UNMASK;
|
||||
drive->io_32bit = 0;
|
||||
}
|
||||
return;
|
||||
@ -1073,12 +1080,13 @@ static void pre_reset(ide_drive_t *drive)
|
||||
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
{
|
||||
unsigned int unit;
|
||||
unsigned long flags;
|
||||
unsigned long flags, timeout;
|
||||
ide_hwif_t *hwif;
|
||||
ide_hwgroup_t *hwgroup;
|
||||
struct ide_io_ports *io_ports;
|
||||
const struct ide_tp_ops *tp_ops;
|
||||
const struct ide_port_ops *port_ops;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
hwif = HWIF(drive);
|
||||
@ -1105,6 +1113,31 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
/* We must not disturb devices in the IDE_DFLAG_PARKED state. */
|
||||
do {
|
||||
unsigned long now;
|
||||
|
||||
prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
|
||||
timeout = jiffies;
|
||||
for (unit = 0; unit < MAX_DRIVES; unit++) {
|
||||
ide_drive_t *tdrive = &hwif->drives[unit];
|
||||
|
||||
if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
|
||||
tdrive->dev_flags & IDE_DFLAG_PARKED &&
|
||||
time_after(tdrive->sleep, timeout))
|
||||
timeout = tdrive->sleep;
|
||||
}
|
||||
|
||||
now = jiffies;
|
||||
if (time_before_eq(timeout, now))
|
||||
break;
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
timeout = schedule_timeout_uninterruptible(timeout - now);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
} while (timeout);
|
||||
finish_wait(&ide_park_wq, &wait);
|
||||
|
||||
/*
|
||||
* First, reset any device state data we were maintaining
|
||||
* for any of the drives on this interface.
|
||||
|
@ -317,7 +317,7 @@ static void ide_dump_sector(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t task;
|
||||
struct ide_taskfile *tf = &task.tf;
|
||||
int lba48 = (drive->addressing == 1) ? 1 : 0;
|
||||
u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
if (lba48)
|
||||
|
121
drivers/ide/ide-park.c
Normal file
121
drivers/ide/ide-park.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
|
||||
|
||||
static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
|
||||
{
|
||||
struct request_queue *q = drive->queue;
|
||||
struct request *rq;
|
||||
int rc;
|
||||
|
||||
timeout += jiffies;
|
||||
spin_lock_irq(&ide_lock);
|
||||
if (drive->dev_flags & IDE_DFLAG_PARKED) {
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
int reset_timer;
|
||||
|
||||
reset_timer = time_before(timeout, drive->sleep);
|
||||
drive->sleep = timeout;
|
||||
wake_up_all(&ide_park_wq);
|
||||
if (reset_timer && hwgroup->sleeping &&
|
||||
del_timer(&hwgroup->timer)) {
|
||||
hwgroup->sleeping = 0;
|
||||
hwgroup->busy = 0;
|
||||
blk_start_queueing(q);
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
rq = blk_get_request(q, READ, __GFP_WAIT);
|
||||
rq->cmd[0] = REQ_PARK_HEADS;
|
||||
rq->cmd_len = 1;
|
||||
rq->cmd_type = REQ_TYPE_SPECIAL;
|
||||
rq->special = &timeout;
|
||||
rc = blk_execute_rq(q, NULL, rq, 1);
|
||||
blk_put_request(rq);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Make sure that *some* command is sent to the drive after the
|
||||
* timeout has expired, so power management will be reenabled.
|
||||
*/
|
||||
rq = blk_get_request(q, READ, GFP_NOWAIT);
|
||||
if (unlikely(!rq))
|
||||
goto out;
|
||||
|
||||
rq->cmd[0] = REQ_UNPARK_HEADS;
|
||||
rq->cmd_len = 1;
|
||||
rq->cmd_type = REQ_TYPE_SPECIAL;
|
||||
elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
unsigned long now;
|
||||
unsigned int msecs;
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
now = jiffies;
|
||||
if (drive->dev_flags & IDE_DFLAG_PARKED &&
|
||||
time_after(drive->sleep, now))
|
||||
msecs = jiffies_to_msecs(drive->sleep - now);
|
||||
else
|
||||
msecs = 0;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
return snprintf(buf, 20, "%u\n", msecs);
|
||||
}
|
||||
|
||||
ssize_t ide_park_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
#define MAX_PARK_TIMEOUT 30000
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
long int input;
|
||||
int rc;
|
||||
|
||||
rc = strict_strtol(buf, 10, &input);
|
||||
if (rc || input < -2)
|
||||
return -EINVAL;
|
||||
if (input > MAX_PARK_TIMEOUT) {
|
||||
input = MAX_PARK_TIMEOUT;
|
||||
rc = -EOVERFLOW;
|
||||
}
|
||||
|
||||
mutex_lock(&ide_setting_mtx);
|
||||
if (input >= 0) {
|
||||
if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
|
||||
rc = -EOPNOTSUPP;
|
||||
else if (input || drive->dev_flags & IDE_DFLAG_PARKED)
|
||||
issue_park_cmd(drive, msecs_to_jiffies(input));
|
||||
} else {
|
||||
if (drive->media == ide_disk)
|
||||
switch (input) {
|
||||
case -1:
|
||||
drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD;
|
||||
break;
|
||||
case -2:
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
|
||||
break;
|
||||
}
|
||||
else
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
mutex_unlock(&ide_setting_mtx);
|
||||
|
||||
return rc ? rc : len;
|
||||
}
|
@ -121,7 +121,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
/* read 512 bytes of id info */
|
||||
hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
|
||||
|
||||
drive->id_read = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_ID_READ;
|
||||
|
||||
local_irq_enable();
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO "%s: dumping identify data\n", drive->name);
|
||||
@ -153,8 +154,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
|
||||
printk(KERN_INFO "%s: %s, ", drive->name, m);
|
||||
|
||||
drive->present = 1;
|
||||
drive->dead = 0;
|
||||
drive->dev_flags |= IDE_DFLAG_PRESENT;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DEAD;
|
||||
|
||||
/*
|
||||
* Check for an ATAPI device
|
||||
@ -172,14 +173,14 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
printk(KERN_CONT "cdrom or floppy?, assuming ");
|
||||
if (drive->media != ide_cdrom) {
|
||||
printk(KERN_CONT "FLOPPY");
|
||||
drive->removable = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_REMOVABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Early cdrom models used zero */
|
||||
type = ide_cdrom;
|
||||
case ide_cdrom:
|
||||
drive->removable = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_REMOVABLE;
|
||||
#ifdef CONFIG_PPC
|
||||
/* kludge for Apple PowerBook internal zip */
|
||||
if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
|
||||
@ -195,7 +196,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
break;
|
||||
case ide_optical:
|
||||
printk(KERN_CONT "OPTICAL");
|
||||
drive->removable = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_REMOVABLE;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_CONT "UNKNOWN (type %d)", type);
|
||||
@ -205,6 +206,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
drive->media = type;
|
||||
/* an ATAPI device ignores DRDY */
|
||||
drive->ready_stat = 0;
|
||||
if (ata_id_cdb_intr(id))
|
||||
drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
|
||||
/* we don't do head unloading on ATAPI devices */
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -216,17 +221,20 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
|
||||
/* CF devices are *not* removable in Linux definition of the term */
|
||||
if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
|
||||
drive->removable = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_REMOVABLE;
|
||||
|
||||
drive->media = ide_disk;
|
||||
|
||||
if (!ata_id_has_unload(drive->id))
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
|
||||
|
||||
printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
|
||||
|
||||
return;
|
||||
|
||||
err_misc:
|
||||
kfree(id);
|
||||
drive->present = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -426,16 +434,15 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
|
||||
int rc;
|
||||
u8 stat;
|
||||
u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
|
||||
|
||||
/* avoid waiting for inappropriate probes */
|
||||
if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
|
||||
return 4;
|
||||
|
||||
if (drive->present) {
|
||||
/* avoid waiting for inappropriate probes */
|
||||
if (drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
|
||||
return 4;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
|
||||
drive->name, drive->present, drive->media,
|
||||
drive->name, present, drive->media,
|
||||
(cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
|
||||
#endif
|
||||
|
||||
@ -446,8 +453,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
||||
SELECT_DRIVE(drive);
|
||||
msleep(50);
|
||||
|
||||
if (ide_read_device(drive) != drive->select.all && !drive->present) {
|
||||
if (drive->select.b.unit != 0) {
|
||||
if (ide_read_device(drive) != drive->select && present == 0) {
|
||||
if (drive->dn & 1) {
|
||||
/* exit with drive0 selected */
|
||||
SELECT_DRIVE(&hwif->drives[0]);
|
||||
/* allow ATA_BUSY to assert & clear */
|
||||
@ -460,7 +467,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
||||
stat = tp_ops->read_status(hwif);
|
||||
|
||||
if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
|
||||
drive->present || cmd == ATA_CMD_ID_ATAPI) {
|
||||
present || cmd == ATA_CMD_ID_ATAPI) {
|
||||
/* send cmd and wait */
|
||||
if ((rc = try_to_identify(drive, cmd))) {
|
||||
/* failed: try again */
|
||||
@ -493,7 +500,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
||||
/* not present or maybe ATAPI */
|
||||
rc = 3;
|
||||
}
|
||||
if (drive->select.b.unit != 0) {
|
||||
if (drive->dn & 1) {
|
||||
/* exit with drive0 selected */
|
||||
SELECT_DRIVE(&hwif->drives[0]);
|
||||
msleep(50);
|
||||
@ -542,8 +549,8 @@ static void enable_nest (ide_drive_t *drive)
|
||||
* and presents things to the user as needed.
|
||||
*
|
||||
* Returns: 0 no device was found
|
||||
* 1 device was found (note: drive->present might
|
||||
* still be 0)
|
||||
* 1 device was found
|
||||
* (note: IDE_DFLAG_PRESENT might still be not set)
|
||||
*/
|
||||
|
||||
static inline u8 probe_for_drive (ide_drive_t *drive)
|
||||
@ -559,10 +566,10 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
|
||||
* Also note that 0 everywhere means "can't do X"
|
||||
*/
|
||||
|
||||
drive->dev_flags &= ~IDE_DFLAG_ID_READ;
|
||||
|
||||
drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
|
||||
drive->id_read = 0;
|
||||
if(drive->id == NULL)
|
||||
{
|
||||
if (drive->id == NULL) {
|
||||
printk(KERN_ERR "ide: out of memory for id data.\n");
|
||||
return 0;
|
||||
}
|
||||
@ -571,14 +578,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
|
||||
strcpy(m, "UNKNOWN");
|
||||
|
||||
/* skip probing? */
|
||||
if (!drive->noprobe) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
|
||||
retry:
|
||||
/* if !(success||timed-out) */
|
||||
if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
|
||||
/* look for ATAPI device */
|
||||
(void)do_probe(drive, ATA_CMD_ID_ATAPI);
|
||||
|
||||
if (!drive->present)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
/* drive not found */
|
||||
return 0;
|
||||
|
||||
@ -588,7 +595,7 @@ retry:
|
||||
}
|
||||
|
||||
/* identification failed? */
|
||||
if (!drive->id_read) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
|
||||
if (drive->media == ide_disk) {
|
||||
printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
|
||||
drive->name, drive->cyl,
|
||||
@ -598,15 +605,17 @@ retry:
|
||||
} else {
|
||||
/* nuke it */
|
||||
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
|
||||
drive->present = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
}
|
||||
}
|
||||
/* drive was found */
|
||||
}
|
||||
if(!drive->present)
|
||||
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
return 0;
|
||||
|
||||
/* The drive wasn't being helpful. Add generic info only */
|
||||
if (drive->id_read == 0) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
|
||||
generic_id(drive);
|
||||
return 1;
|
||||
}
|
||||
@ -616,7 +625,7 @@ retry:
|
||||
ide_disk_init_mult_count(drive);
|
||||
}
|
||||
|
||||
return drive->present;
|
||||
return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
|
||||
}
|
||||
|
||||
static void hwif_release_dev(struct device *dev)
|
||||
@ -707,7 +716,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
||||
/* Ignore disks that we will not probe for later. */
|
||||
if (!drive->noprobe || drive->present) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_PRESENT)) {
|
||||
SELECT_DRIVE(drive);
|
||||
hwif->tp_ops->set_irq(hwif, 1);
|
||||
mdelay(2);
|
||||
@ -739,7 +749,7 @@ void ide_undecoded_slave(ide_drive_t *dev1)
|
||||
{
|
||||
ide_drive_t *dev0 = &dev1->hwif->drives[0];
|
||||
|
||||
if ((dev1->dn & 1) == 0 || dev0->present == 0)
|
||||
if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
return;
|
||||
|
||||
/* If the models don't match they are not the same product */
|
||||
@ -759,7 +769,7 @@ void ide_undecoded_slave(ide_drive_t *dev1)
|
||||
/* Appears to be an IDE flash adapter with decode bugs */
|
||||
printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
|
||||
|
||||
dev1->present = 0;
|
||||
dev1->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_undecoded_slave);
|
||||
@ -772,7 +782,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
|
||||
|
||||
BUG_ON(hwif->present);
|
||||
|
||||
if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
|
||||
if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) &&
|
||||
(hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE))
|
||||
return -EACCES;
|
||||
|
||||
/*
|
||||
@ -794,9 +805,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
|
||||
*/
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
drive->dn = (hwif->channel ? 2 : 0) + unit;
|
||||
|
||||
(void) probe_for_drive(drive);
|
||||
if (drive->present)
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT)
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
@ -820,17 +831,19 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
|
||||
for (unit = 0; unit < MAX_DRIVES; unit++) {
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
||||
if (drive->present && port_ops && port_ops->quirkproc)
|
||||
port_ops->quirkproc(drive);
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
if (port_ops && port_ops->quirkproc)
|
||||
port_ops->quirkproc(drive);
|
||||
}
|
||||
}
|
||||
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
||||
if (drive->present) {
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
ide_set_max_pio(drive);
|
||||
|
||||
drive->nice1 = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NICE1;
|
||||
|
||||
if (hwif->dma_ops)
|
||||
ide_set_dma(drive);
|
||||
@ -840,14 +853,14 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
||||
if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
|
||||
drive->no_io_32bit = 1;
|
||||
if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) ||
|
||||
drive->id[ATA_ID_DWORD_IO])
|
||||
drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
|
||||
else
|
||||
drive->no_io_32bit = drive->id[ATA_ID_DWORD_IO] ? 1 : 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
#if MAX_HWIFS > 1
|
||||
/*
|
||||
* save_match() is used to simplify logic in init_irq() below.
|
||||
*
|
||||
@ -872,7 +885,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
|
||||
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
|
||||
*match = new;
|
||||
}
|
||||
#endif /* MAX_HWIFS > 1 */
|
||||
|
||||
/*
|
||||
* init request queue
|
||||
@ -951,26 +963,33 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
|
||||
* - allocate the block device queue
|
||||
* - link drive into the hwgroup
|
||||
*/
|
||||
static void ide_port_setup_devices(ide_hwif_t *hwif)
|
||||
static int ide_port_setup_devices(ide_hwif_t *hwif)
|
||||
{
|
||||
int i;
|
||||
int i, j = 0;
|
||||
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
for (i = 0; i < MAX_DRIVES; i++) {
|
||||
ide_drive_t *drive = &hwif->drives[i];
|
||||
|
||||
if (!drive->present)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
continue;
|
||||
|
||||
if (ide_init_queue(drive)) {
|
||||
printk(KERN_ERR "ide: failed to init %s\n",
|
||||
drive->name);
|
||||
kfree(drive->id);
|
||||
drive->id = NULL;
|
||||
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
continue;
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
ide_add_drive_to_hwgroup(drive);
|
||||
}
|
||||
mutex_unlock(&ide_cfg_mtx);
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static ide_hwif_t *ide_ports[MAX_HWIFS];
|
||||
@ -1029,7 +1048,7 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
hwif->hwgroup = NULL;
|
||||
#if MAX_HWIFS > 1
|
||||
|
||||
/*
|
||||
* Group up with any other hwifs that share our irq(s).
|
||||
*/
|
||||
@ -1054,7 +1073,7 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MAX_HWIFS > 1 */
|
||||
|
||||
/*
|
||||
* If we are still without a hwgroup, then form a new one
|
||||
*/
|
||||
@ -1153,12 +1172,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
|
||||
ide_hwif_t *hwif = data;
|
||||
int unit = *part >> PARTN_BITS;
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
if (!drive->present)
|
||||
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
return NULL;
|
||||
|
||||
if (drive->media == ide_disk)
|
||||
request_module("ide-disk");
|
||||
if (drive->scsi)
|
||||
if (drive->dev_flags & IDE_DFLAG_SCSI)
|
||||
request_module("ide-scsi");
|
||||
if (drive->media == ide_cdrom || drive->media == ide_optical)
|
||||
request_module("ide-cd");
|
||||
@ -1205,7 +1225,7 @@ 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 >> 4) & 1;
|
||||
unsigned int unit = drive->dn & 1;
|
||||
|
||||
disk->major = hwif->major;
|
||||
disk->first_minor = unit << PARTN_BITS;
|
||||
@ -1248,7 +1268,7 @@ static void drive_release_dev (struct device *dev)
|
||||
ide_remove_drive_from_hwgroup(drive);
|
||||
kfree(drive->id);
|
||||
drive->id = NULL;
|
||||
drive->present = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
/* Messed up locking ... */
|
||||
spin_unlock_irq(&ide_lock);
|
||||
blk_cleanup_queue(drive->queue);
|
||||
@ -1327,7 +1347,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
|
||||
struct device *dev = &drive->gendev;
|
||||
int ret;
|
||||
|
||||
if (!drive->present)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
continue;
|
||||
|
||||
snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
|
||||
@ -1351,12 +1371,14 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
|
||||
for (i = 0; i < MAX_DRIVES; i++) {
|
||||
ide_drive_t *drive = &hwif->drives[i];
|
||||
|
||||
drive->dn = i + hwif->channel * 2;
|
||||
|
||||
if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
|
||||
drive->io_32bit = 1;
|
||||
if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
|
||||
drive->unmask = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_UNMASK;
|
||||
if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
|
||||
drive->no_unmask = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
|
||||
|
||||
if (port_ops && port_ops->init_dev)
|
||||
port_ops->init_dev(drive);
|
||||
@ -1513,19 +1535,14 @@ static int ide_find_port_slot(const struct ide_port_info *d)
|
||||
* ports 0x1f0/0x170 (the ide0/ide1 defaults).
|
||||
*/
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
if (MAX_HWIFS == 1) {
|
||||
if (ide_indexes == 0 && i == 0)
|
||||
idx = 1;
|
||||
if (bootable) {
|
||||
if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
|
||||
idx = ffz(ide_indexes | i);
|
||||
} else {
|
||||
if (bootable) {
|
||||
if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
|
||||
idx = ffz(ide_indexes | i);
|
||||
} else {
|
||||
if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
|
||||
idx = ffz(ide_indexes | 3);
|
||||
else if ((ide_indexes & 3) != 3)
|
||||
idx = ffz(ide_indexes);
|
||||
}
|
||||
if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
|
||||
idx = ffz(ide_indexes | 3);
|
||||
else if ((ide_indexes & 3) != 3)
|
||||
idx = ffz(ide_indexes);
|
||||
}
|
||||
if (idx >= 0)
|
||||
ide_indexes |= (1 << idx);
|
||||
@ -1541,8 +1558,7 @@ static void ide_free_port_slot(int idx)
|
||||
mutex_unlock(&ide_cfg_mtx);
|
||||
}
|
||||
|
||||
struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
|
||||
hw_regs_t **hws)
|
||||
struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
|
||||
{
|
||||
struct ide_host *host;
|
||||
int i;
|
||||
@ -1551,7 +1567,7 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
|
||||
if (host == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
ide_hwif_t *hwif;
|
||||
int idx;
|
||||
|
||||
@ -1593,18 +1609,6 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
|
||||
|
||||
return host;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_host_alloc_all);
|
||||
|
||||
struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
|
||||
{
|
||||
hw_regs_t *hws_all[MAX_HWIFS];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++)
|
||||
hws_all[i] = (i < 4) ? hws[i] : NULL;
|
||||
|
||||
return ide_host_alloc_all(d, hws_all);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_host_alloc);
|
||||
|
||||
int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
@ -1613,7 +1617,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
ide_hwif_t *hwif, *mate = NULL;
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL) {
|
||||
@ -1626,22 +1630,22 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
|
||||
if (d == NULL) {
|
||||
mate = NULL;
|
||||
continue;
|
||||
} else {
|
||||
if ((i & 1) && mate) {
|
||||
hwif->mate = mate;
|
||||
mate->mate = hwif;
|
||||
}
|
||||
|
||||
mate = (i & 1) ? NULL : hwif;
|
||||
|
||||
ide_init_port(hwif, i & 1, d);
|
||||
ide_port_cable_detect(hwif);
|
||||
}
|
||||
|
||||
if ((i & 1) && mate) {
|
||||
hwif->mate = mate;
|
||||
mate->mate = hwif;
|
||||
}
|
||||
|
||||
mate = (i & 1) ? NULL : hwif;
|
||||
|
||||
ide_init_port(hwif, i & 1, d);
|
||||
ide_port_cable_detect(hwif);
|
||||
ide_port_init_devices(hwif);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL)
|
||||
@ -1658,7 +1662,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
ide_port_tune_devices(hwif);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL)
|
||||
@ -1671,10 +1675,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
continue;
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
if (hwif->present)
|
||||
ide_port_setup_devices(hwif);
|
||||
if (ide_port_setup_devices(hwif) == 0) {
|
||||
hwif->present = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
ide_acpi_init(hwif);
|
||||
|
||||
@ -1682,7 +1689,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
ide_acpi_port_init_devices(hwif);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL)
|
||||
@ -1695,7 +1702,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
|
||||
hwif_register_devices(hwif);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL)
|
||||
@ -1740,7 +1747,7 @@ void ide_host_free(struct ide_host *host)
|
||||
ide_hwif_t *hwif;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
hwif = host->ports[i];
|
||||
|
||||
if (hwif == NULL)
|
||||
@ -1758,7 +1765,7 @@ void ide_host_remove(struct ide_host *host)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_HWIFS; i++) {
|
||||
for (i = 0; i < MAX_HOST_PORTS; i++) {
|
||||
if (host->ports[i])
|
||||
ide_unregister(host->ports[i]);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
|
||||
|
||||
ide_devset_rw(current_speed, xfer_rate);
|
||||
ide_devset_rw_field(init_speed, init_speed);
|
||||
ide_devset_rw_field(nice1, nice1);
|
||||
ide_devset_rw_flag(nice1, IDE_DFLAG_NICE1);
|
||||
ide_devset_rw_field(number, dn);
|
||||
|
||||
static const struct ide_proc_devset ide_generic_settings[] = {
|
||||
@ -622,9 +622,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
|
||||
for (d = 0; d < MAX_DRIVES; d++) {
|
||||
ide_drive_t *drive = &hwif->drives[d];
|
||||
|
||||
if (!drive->present)
|
||||
continue;
|
||||
if (drive->proc)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
|
||||
continue;
|
||||
|
||||
drive->proc = proc_mkdir(drive->name, parent);
|
||||
|
@ -172,23 +172,16 @@ typedef struct ide_tape_obj {
|
||||
struct kref kref;
|
||||
|
||||
/*
|
||||
* pc points to the current processed packet command.
|
||||
*
|
||||
* failed_pc points to the last failed packet command, or contains
|
||||
* NULL if we do not need to retry any packet command. This is
|
||||
* required since an additional packet command is needed before the
|
||||
* retry, to get detailed information on what went wrong.
|
||||
*/
|
||||
/* Current packet command */
|
||||
struct ide_atapi_pc *pc;
|
||||
/* Last failed packet command */
|
||||
struct ide_atapi_pc *failed_pc;
|
||||
/* used by REQ_IDETAPE_{READ,WRITE} requests */
|
||||
struct ide_atapi_pc queued_pc;
|
||||
|
||||
struct ide_atapi_pc request_sense_pc;
|
||||
struct request request_sense_rq;
|
||||
|
||||
/*
|
||||
* DSC polling variables.
|
||||
*
|
||||
@ -274,11 +267,6 @@ static DEFINE_MUTEX(idetape_ref_mutex);
|
||||
|
||||
static struct class *idetape_sysfs_class;
|
||||
|
||||
#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 void ide_tape_release(struct kref *);
|
||||
|
||||
static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
|
||||
@ -286,7 +274,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
|
||||
struct ide_tape_obj *tape = NULL;
|
||||
|
||||
mutex_lock(&idetape_ref_mutex);
|
||||
tape = ide_tape_g(disk);
|
||||
tape = ide_drv_g(disk, ide_tape_obj);
|
||||
if (tape) {
|
||||
if (ide_device_get(tape->drive))
|
||||
tape = NULL;
|
||||
@ -313,8 +301,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
|
||||
*/
|
||||
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;
|
||||
@ -522,14 +508,19 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_tape_callback(ide_drive_t *drive)
|
||||
static void ide_tape_handle_dsc(ide_drive_t *);
|
||||
|
||||
static void ide_tape_callback(ide_drive_t *drive, int dsc)
|
||||
{
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
struct ide_atapi_pc *pc = tape->pc;
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
int uptodate = pc->error ? 0 : 1;
|
||||
|
||||
debug_log(DBG_PROCS, "Enter %s\n", __func__);
|
||||
|
||||
if (dsc)
|
||||
ide_tape_handle_dsc(drive);
|
||||
|
||||
if (tape->failed_pc == pc)
|
||||
tape->failed_pc = NULL;
|
||||
|
||||
@ -558,7 +549,7 @@ static void ide_tape_callback(ide_drive_t *drive)
|
||||
if (pc->error)
|
||||
uptodate = pc->error;
|
||||
} else if (pc->c[0] == READ_POSITION && uptodate) {
|
||||
u8 *readpos = tape->pc->buf;
|
||||
u8 *readpos = pc->buf;
|
||||
|
||||
debug_log(DBG_SENSE, "BOP - %s\n",
|
||||
(readpos[0] & 0x80) ? "Yes" : "No");
|
||||
@ -583,31 +574,6 @@ static void ide_tape_callback(ide_drive_t *drive)
|
||||
idetape_end_request(drive, uptodate, 0);
|
||||
}
|
||||
|
||||
static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
|
||||
{
|
||||
ide_init_pc(pc);
|
||||
pc->c[0] = REQUEST_SENSE;
|
||||
pc->c[4] = 20;
|
||||
pc->req_xfer = 20;
|
||||
}
|
||||
|
||||
/*
|
||||
* idetape_retry_pc is called when an error was detected during the
|
||||
* last packet command. We queue a request sense packet command in
|
||||
* the head of the request list.
|
||||
*/
|
||||
static void idetape_retry_pc(ide_drive_t *drive)
|
||||
{
|
||||
struct ide_tape_obj *tape = drive->driver_data;
|
||||
struct request *rq = &tape->request_sense_rq;
|
||||
struct ide_atapi_pc *pc = &tape->request_sense_pc;
|
||||
|
||||
(void)ide_read_error(drive);
|
||||
idetape_create_request_sense_cmd(pc);
|
||||
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
|
||||
ide_queue_pc_head(drive, tape->disk, pc, rq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Postpone the current request so that ide.c will be able to service requests
|
||||
* from another device on the same hwgroup while we are polling for DSC.
|
||||
@ -645,35 +611,19 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
|
||||
return bcount;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the usual interrupt handler which will be called during a packet
|
||||
* command. We will transfer some of the data (as requested by the drive) and
|
||||
* will re-point interrupt handler to us. When data transfer is finished, we
|
||||
* will act according to the algorithm described before
|
||||
* idetape_issue_pc.
|
||||
*/
|
||||
static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
|
||||
{
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
|
||||
return ide_pc_intr(drive, tape->pc, idetape_pc_intr, WAIT_TAPE_CMD,
|
||||
NULL, idetape_update_buffers, idetape_retry_pc,
|
||||
ide_tape_handle_dsc, ide_tape_io_buffers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Packet Command Interface
|
||||
*
|
||||
* The current Packet Command is available in tape->pc, and will not change
|
||||
* The current Packet Command is available in drive->pc, and will not change
|
||||
* until we finish handling it. Each packet command is associated with a
|
||||
* callback function that will be called when the command is finished.
|
||||
*
|
||||
* The handling will be done in three stages:
|
||||
*
|
||||
* 1. idetape_issue_pc will send the packet command to the drive, and will set
|
||||
* the interrupt handler to idetape_pc_intr.
|
||||
* the interrupt handler to ide_pc_intr.
|
||||
*
|
||||
* 2. On each interrupt, idetape_pc_intr will be called. This step will be
|
||||
* 2. On each interrupt, ide_pc_intr will be called. This step will be
|
||||
* repeated until the device signals us that no more interrupts will be issued.
|
||||
*
|
||||
* 3. ATAPI Tape media access commands have immediate status with a delayed
|
||||
@ -697,20 +647,13 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
|
||||
* again, the callback function will be called and then we will handle the next
|
||||
* request.
|
||||
*/
|
||||
static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
|
||||
{
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
|
||||
return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
|
||||
WAIT_TAPE_CMD, NULL);
|
||||
}
|
||||
|
||||
static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
|
||||
struct ide_atapi_pc *pc)
|
||||
{
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
|
||||
if (tape->pc->c[0] == REQUEST_SENSE &&
|
||||
if (drive->pc->c[0] == REQUEST_SENSE &&
|
||||
pc->c[0] == REQUEST_SENSE) {
|
||||
printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
|
||||
"Two request sense in serial were issued\n");
|
||||
@ -718,8 +661,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
|
||||
|
||||
if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
|
||||
tape->failed_pc = pc;
|
||||
|
||||
/* Set the current packet command */
|
||||
tape->pc = pc;
|
||||
drive->pc = pc;
|
||||
|
||||
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
|
||||
(pc->flags & PC_FLAG_ABORT)) {
|
||||
@ -743,15 +687,14 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
|
||||
pc->error = IDETAPE_ERROR_GENERAL;
|
||||
}
|
||||
tape->failed_pc = NULL;
|
||||
drive->pc_callback(drive);
|
||||
drive->pc_callback(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
|
||||
|
||||
pc->retries++;
|
||||
|
||||
return ide_issue_pc(drive, pc, idetape_transfer_pc,
|
||||
WAIT_TAPE_CMD, NULL);
|
||||
return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
|
||||
}
|
||||
|
||||
/* A mode sense command is used to "sense" tape parameters. */
|
||||
@ -785,7 +728,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
struct ide_atapi_pc *pc = tape->pc;
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
u8 stat;
|
||||
|
||||
stat = hwif->tp_ops->read_status(hwif);
|
||||
@ -797,7 +740,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
|
||||
printk(KERN_ERR "ide-tape: %s: I/O error, ",
|
||||
tape->name);
|
||||
/* Retry operation */
|
||||
idetape_retry_pc(drive);
|
||||
ide_retry_pc(drive, tape->disk);
|
||||
return ide_stopped;
|
||||
}
|
||||
pc->error = 0;
|
||||
@ -805,7 +748,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
|
||||
pc->error = IDETAPE_ERROR_GENERAL;
|
||||
tape->failed_pc = NULL;
|
||||
}
|
||||
drive->pc_callback(drive);
|
||||
drive->pc_callback(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
@ -862,7 +805,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
||||
}
|
||||
|
||||
/* Retry a failed packet command */
|
||||
if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) {
|
||||
if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
|
||||
pc = tape->failed_pc;
|
||||
goto out;
|
||||
}
|
||||
@ -883,12 +826,13 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
||||
*/
|
||||
stat = hwif->tp_ops->read_status(hwif);
|
||||
|
||||
if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
|
||||
if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
|
||||
(rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
|
||||
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
|
||||
|
||||
if (drive->post_reset == 1) {
|
||||
if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
|
||||
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
|
||||
drive->post_reset = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
|
||||
}
|
||||
|
||||
if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
|
||||
@ -1411,7 +1355,7 @@ static int idetape_init_read(ide_drive_t *drive)
|
||||
* No point in issuing this if DSC overlap isn't supported, some
|
||||
* drives (Seagate STT3401A) will return an error.
|
||||
*/
|
||||
if (drive->dsc_overlap) {
|
||||
if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
|
||||
bytes_read = idetape_queue_rw_tail(drive,
|
||||
REQ_IDETAPE_READ, 0,
|
||||
tape->merge_bh);
|
||||
@ -1592,7 +1536,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
|
||||
static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ide_tape_obj *tape = ide_tape_f(file);
|
||||
struct ide_tape_obj *tape = file->private_data;
|
||||
ide_drive_t *drive = tape->drive;
|
||||
ssize_t bytes_read, temp, actually_read = 0, rc;
|
||||
ssize_t ret = 0;
|
||||
@ -1654,7 +1598,7 @@ finish:
|
||||
static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ide_tape_obj *tape = ide_tape_f(file);
|
||||
struct ide_tape_obj *tape = file->private_data;
|
||||
ide_drive_t *drive = tape->drive;
|
||||
ssize_t actually_written = 0;
|
||||
ssize_t ret = 0;
|
||||
@ -1687,7 +1631,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
|
||||
* point in issuing this if DSC overlap isn't supported, some
|
||||
* drives (Seagate STT3401A) will return an error.
|
||||
*/
|
||||
if (drive->dsc_overlap) {
|
||||
if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
|
||||
ssize_t retval = idetape_queue_rw_tail(drive,
|
||||
REQ_IDETAPE_WRITE, 0,
|
||||
tape->merge_bh);
|
||||
@ -1886,7 +1830,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
|
||||
static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct ide_tape_obj *tape = ide_tape_f(file);
|
||||
struct ide_tape_obj *tape = file->private_data;
|
||||
ide_drive_t *drive = tape->drive;
|
||||
struct mtop mtop;
|
||||
struct mtget mtget;
|
||||
@ -2063,7 +2007,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
|
||||
|
||||
static int idetape_chrdev_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct ide_tape_obj *tape = ide_tape_f(filp);
|
||||
struct ide_tape_obj *tape = filp->private_data;
|
||||
ide_drive_t *drive = tape->drive;
|
||||
unsigned int minor = iminor(inode);
|
||||
|
||||
@ -2202,7 +2146,7 @@ static int divf_tdsc(ide_drive_t *drive) { return HZ; }
|
||||
static int divf_buffer(ide_drive_t *drive) { return 2; }
|
||||
static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
|
||||
|
||||
ide_devset_rw_field(dsc_overlap, dsc_overlap);
|
||||
ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
|
||||
|
||||
ide_tape_devset_rw_field(debug_mask, debug_mask);
|
||||
ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
|
||||
@ -2241,33 +2185,32 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
||||
unsigned long t;
|
||||
int speed;
|
||||
int buffer_size;
|
||||
u8 gcw[2];
|
||||
u16 *ctl = (u16 *)&tape->caps[12];
|
||||
|
||||
drive->pc_callback = ide_tape_callback;
|
||||
drive->pc_callback = ide_tape_callback;
|
||||
drive->pc_update_buffers = idetape_update_buffers;
|
||||
drive->pc_io_buffers = ide_tape_io_buffers;
|
||||
|
||||
spin_lock_init(&tape->lock);
|
||||
drive->dsc_overlap = 1;
|
||||
|
||||
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
|
||||
|
||||
if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
|
||||
printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
|
||||
tape->name);
|
||||
drive->dsc_overlap = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
}
|
||||
|
||||
/* Seagate Travan drives do not support DSC overlap. */
|
||||
if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
|
||||
drive->dsc_overlap = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
|
||||
tape->minor = minor;
|
||||
tape->name[0] = 'h';
|
||||
tape->name[1] = 't';
|
||||
tape->name[2] = '0' + minor;
|
||||
tape->chrdev_dir = IDETAPE_DIR_NONE;
|
||||
|
||||
*((u16 *)&gcw) = drive->id[ATA_ID_CONFIG];
|
||||
|
||||
/* Command packet DRQ type */
|
||||
if (((gcw[0] & 0x60) >> 5) == 1)
|
||||
set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
|
||||
|
||||
idetape_get_inquiry_results(drive);
|
||||
idetape_get_mode_sense_results(drive);
|
||||
ide_tape_get_bsize_from_bdesc(drive);
|
||||
@ -2302,7 +2245,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
||||
(*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
|
||||
tape->buffer_size / 1024,
|
||||
tape->best_dsc_rw_freq * 1000 / HZ,
|
||||
drive->using_dma ? ", DMA":"");
|
||||
(drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
|
||||
|
||||
ide_proc_register_driver(drive, tape->driver);
|
||||
}
|
||||
@ -2320,13 +2263,13 @@ static void ide_tape_remove(ide_drive_t *drive)
|
||||
|
||||
static void ide_tape_release(struct kref *kref)
|
||||
{
|
||||
struct ide_tape_obj *tape = to_ide_tape(kref);
|
||||
struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
|
||||
ide_drive_t *drive = tape->drive;
|
||||
struct gendisk *g = tape->disk;
|
||||
|
||||
BUG_ON(tape->merge_bh_size);
|
||||
|
||||
drive->dsc_overlap = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
drive->driver_data = NULL;
|
||||
device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
|
||||
device_destroy(idetape_sysfs_class,
|
||||
@ -2368,7 +2311,6 @@ static ide_driver_t idetape_driver = {
|
||||
.probe = ide_tape_probe,
|
||||
.remove = ide_tape_remove,
|
||||
.version = IDETAPE_VERSION,
|
||||
.media = ide_tape,
|
||||
.do_request = idetape_do_request,
|
||||
.end_request = idetape_end_request,
|
||||
.error = __ide_error,
|
||||
@ -2403,7 +2345,7 @@ static int idetape_open(struct inode *inode, struct file *filp)
|
||||
static int idetape_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||
struct ide_tape_obj *tape = ide_tape_g(disk);
|
||||
struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
|
||||
|
||||
ide_tape_put(tape);
|
||||
|
||||
@ -2414,7 +2356,7 @@ static int idetape_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
|
||||
struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
|
||||
ide_drive_t *drive = tape->drive;
|
||||
int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
|
||||
if (err == -EINVAL)
|
||||
@ -2441,7 +2383,8 @@ static int ide_tape_probe(ide_drive_t *drive)
|
||||
if (drive->media != ide_tape)
|
||||
goto failed;
|
||||
|
||||
if (drive->id_read == 1 && !ide_check_atapi_device(drive, DRV_NAME)) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
|
||||
ide_check_atapi_device(drive, DRV_NAME) == 0) {
|
||||
printk(KERN_ERR "ide-tape: %s: not supported by this version of"
|
||||
" the driver\n", drive->name);
|
||||
goto failed;
|
||||
|
@ -53,9 +53,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
|
||||
}
|
||||
|
||||
static ide_startstop_t task_no_data_intr(ide_drive_t *);
|
||||
static ide_startstop_t set_geometry_intr(ide_drive_t *);
|
||||
static ide_startstop_t recal_intr(ide_drive_t *);
|
||||
static ide_startstop_t set_multmode_intr(ide_drive_t *);
|
||||
static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
|
||||
static ide_startstop_t task_in_intr(ide_drive_t *);
|
||||
|
||||
@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
if (task->tf_flags & IDE_TFLAG_FLAGGED)
|
||||
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
|
||||
|
||||
memcpy(&hwif->task, task, sizeof(*task));
|
||||
|
||||
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
|
||||
ide_tf_dump(drive->name, tf);
|
||||
tp_ops->set_irq(hwif, 1);
|
||||
@ -99,24 +98,12 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
case TASKFILE_NO_DATA:
|
||||
if (handler == NULL)
|
||||
handler = task_no_data_intr;
|
||||
if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
|
||||
switch (tf->command) {
|
||||
case ATA_CMD_INIT_DEV_PARAMS:
|
||||
handler = set_geometry_intr;
|
||||
break;
|
||||
case ATA_CMD_RESTORE:
|
||||
handler = recal_intr;
|
||||
break;
|
||||
case ATA_CMD_SET_MULTI:
|
||||
handler = set_multmode_intr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ide_execute_command(drive, tf->command, handler,
|
||||
WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
default:
|
||||
if (drive->using_dma == 0 || dma_ops->dma_setup(drive))
|
||||
if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
|
||||
dma_ops->dma_setup(drive))
|
||||
return ide_stopped;
|
||||
dma_ops->dma_exec_cmd(drive, tf->command);
|
||||
dma_ops->dma_start(drive);
|
||||
@ -126,33 +113,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
EXPORT_SYMBOL_GPL(do_rw_taskfile);
|
||||
|
||||
/*
|
||||
* set_multmode_intr() is invoked on completion of a ATA_CMD_SET_MULTI cmd.
|
||||
* Handler for commands without a data phase
|
||||
*/
|
||||
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
|
||||
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 stat;
|
||||
|
||||
local_irq_enable_in_hardirq();
|
||||
stat = hwif->tp_ops->read_status(hwif);
|
||||
|
||||
if (OK_STAT(stat, ATA_DRDY, BAD_STAT))
|
||||
drive->mult_count = drive->mult_req;
|
||||
else {
|
||||
drive->mult_req = drive->mult_count = 0;
|
||||
drive->special.b.recalibrate = 1;
|
||||
(void) ide_dump_status(drive, "set_multmode", stat);
|
||||
}
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_geometry_intr() is invoked on completion of a ATA_CMD_INIT_DEV_PARAMS cmd.
|
||||
*/
|
||||
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int retries = 5;
|
||||
ide_task_t *task = &hwif->task;
|
||||
struct ide_taskfile *tf = &task->tf;
|
||||
int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
|
||||
int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
|
||||
u8 stat;
|
||||
|
||||
local_irq_enable_in_hardirq();
|
||||
@ -164,50 +133,36 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
|
||||
udelay(10);
|
||||
};
|
||||
|
||||
if (OK_STAT(stat, ATA_DRDY, BAD_STAT))
|
||||
return ide_stopped;
|
||||
|
||||
if (stat & (ATA_ERR | ATA_DRQ))
|
||||
return ide_error(drive, "set_geometry_intr", stat);
|
||||
|
||||
ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
/*
|
||||
* recal_intr() is invoked on completion of a ATA_CMD_RESTORE (recalibrate) cmd.
|
||||
*/
|
||||
static ide_startstop_t recal_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 stat;
|
||||
|
||||
local_irq_enable_in_hardirq();
|
||||
stat = hwif->tp_ops->read_status(hwif);
|
||||
|
||||
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
|
||||
return ide_error(drive, "recal_intr", stat);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for commands without a data phase
|
||||
*/
|
||||
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_task_t *args = hwif->hwgroup->rq->special;
|
||||
u8 stat;
|
||||
|
||||
local_irq_enable_in_hardirq();
|
||||
stat = hwif->tp_ops->read_status(hwif);
|
||||
|
||||
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
|
||||
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
|
||||
if (custom && tf->command == ATA_CMD_SET_MULTI) {
|
||||
drive->mult_req = drive->mult_count = 0;
|
||||
drive->special.b.recalibrate = 1;
|
||||
(void)ide_dump_status(drive, __func__, stat);
|
||||
return ide_stopped;
|
||||
} else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
|
||||
if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
|
||||
ide_set_handler(drive, &task_no_data_intr,
|
||||
WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
}
|
||||
}
|
||||
return ide_error(drive, "task_no_data_intr", stat);
|
||||
/* calls ide_end_drive_cmd */
|
||||
}
|
||||
|
||||
if (args)
|
||||
if (!custom)
|
||||
ide_end_drive_cmd(drive, stat, ide_read_error(drive));
|
||||
else if (tf->command == ATA_CMD_IDLEIMMEDIATE) {
|
||||
hwif->tp_ops->tf_read(drive, task);
|
||||
if (tf->lbal != 0xc4) {
|
||||
printk(KERN_ERR "%s: head unload failed!\n",
|
||||
drive->name);
|
||||
ide_tf_dump(drive->name, tf);
|
||||
} else
|
||||
drive->dev_flags |= IDE_DFLAG_PARKED;
|
||||
ide_end_drive_cmd(drive, stat, ide_read_error(drive));
|
||||
} else if (tf->command == ATA_CMD_SET_MULTI)
|
||||
drive->mult_count = drive->mult_req;
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -469,13 +424,12 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
|
||||
if (ide_wait_stat(&startstop, drive, ATA_DRQ,
|
||||
drive->bad_wstat, WAIT_DRQ)) {
|
||||
printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
|
||||
drive->name,
|
||||
drive->hwif->data_phase ? "MULT" : "",
|
||||
drive->addressing ? "_EXT" : "");
|
||||
drive->name, drive->hwif->data_phase ? "MULT" : "",
|
||||
(drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
|
||||
return startstop;
|
||||
}
|
||||
|
||||
if (!drive->unmask)
|
||||
if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
|
||||
local_irq_disable();
|
||||
|
||||
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
|
||||
@ -591,7 +545,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
||||
|
||||
args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
|
||||
IDE_TFLAG_IN_TF;
|
||||
if (drive->addressing == 1)
|
||||
if (drive->dev_flags & IDE_DFLAG_LBA48)
|
||||
args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
|
||||
|
||||
if (req_task->out_flags.all) {
|
||||
@ -694,7 +648,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
||||
if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
|
||||
req_task->in_flags.all == 0) {
|
||||
req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
|
||||
if (drive->addressing == 1)
|
||||
if (drive->dev_flags & IDE_DFLAG_LBA48)
|
||||
req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
|
||||
memset(drive, 0, sizeof(*drive));
|
||||
|
||||
drive->media = ide_disk;
|
||||
drive->select.all = (unit<<4)|0xa0;
|
||||
drive->select = (unit << 4) | ATA_DEVICE_OBS;
|
||||
drive->hwif = hwif;
|
||||
drive->ready_stat = ATA_DRDY;
|
||||
drive->bad_wstat = BAD_W_STAT;
|
||||
@ -138,7 +138,7 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
|
||||
for (i = 0; i < MAX_DRIVES; i++) {
|
||||
ide_drive_t *drive = &hwif->drives[i];
|
||||
|
||||
if (drive->present) {
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
spin_unlock_irq(&ide_lock);
|
||||
device_unregister(&drive->gendev);
|
||||
wait_for_completion(&drive->gendev_rel_comp);
|
||||
@ -227,8 +227,7 @@ void ide_unregister(ide_hwif_t *hwif)
|
||||
kfree(hwif->sg_table);
|
||||
unregister_blkdev(hwif->major, hwif->name);
|
||||
|
||||
if (hwif->dma_base)
|
||||
ide_release_dma_engine(hwif);
|
||||
ide_release_dma_engine(hwif);
|
||||
|
||||
mutex_unlock(&ide_cfg_mtx);
|
||||
}
|
||||
@ -254,7 +253,7 @@ ide_devset_get(io_32bit, io_32bit);
|
||||
|
||||
static int set_io_32bit(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (drive->no_io_32bit)
|
||||
if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
|
||||
return -EPERM;
|
||||
|
||||
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
|
||||
@ -265,19 +264,22 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(ksettings, keep_settings);
|
||||
ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
|
||||
|
||||
static int set_ksettings(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
drive->keep_settings = arg;
|
||||
if (arg)
|
||||
drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(using_dma, using_dma);
|
||||
ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
|
||||
|
||||
static int set_using_dma(ide_drive_t *drive, int arg)
|
||||
{
|
||||
@ -311,9 +313,32 @@ out:
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
|
||||
*/
|
||||
static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
|
||||
{
|
||||
switch (req_pio) {
|
||||
case 202:
|
||||
case 201:
|
||||
case 200:
|
||||
case 102:
|
||||
case 101:
|
||||
case 100:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
|
||||
case 9:
|
||||
case 8:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
|
||||
case 7:
|
||||
case 6:
|
||||
return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
{
|
||||
struct request *rq;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
const struct ide_port_ops *port_ops = hwif->port_ops;
|
||||
|
||||
@ -324,56 +349,65 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
(hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
|
||||
return -ENOSYS;
|
||||
|
||||
if (drive->special.b.set_tune)
|
||||
return -EBUSY;
|
||||
if (set_pio_mode_abuse(drive->hwif, arg)) {
|
||||
if (arg == 8 || arg == 9) {
|
||||
unsigned long flags;
|
||||
|
||||
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
|
||||
/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
} else
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
} else {
|
||||
int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
||||
|
||||
drive->tune_req = (u8) arg;
|
||||
drive->special.b.set_tune = 1;
|
||||
ide_set_pio(drive, arg);
|
||||
|
||||
blk_execute_rq(drive->queue, NULL, rq, 0);
|
||||
blk_put_request(rq);
|
||||
if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
|
||||
if (keep_dma)
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(unmaskirq, unmask);
|
||||
ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
|
||||
|
||||
static int set_unmaskirq(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (drive->no_unmask)
|
||||
if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
|
||||
return -EPERM;
|
||||
|
||||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
drive->unmask = arg;
|
||||
if (arg)
|
||||
drive->dev_flags |= IDE_DFLAG_UNMASK;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_UNMASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ide_gen_devset_rw(_name, _func) \
|
||||
__IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
|
||||
|
||||
ide_gen_devset_rw(io_32bit, io_32bit);
|
||||
ide_gen_devset_rw(keepsettings, ksettings);
|
||||
ide_gen_devset_rw(unmaskirq, unmaskirq);
|
||||
ide_gen_devset_rw(using_dma, using_dma);
|
||||
__IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode);
|
||||
ide_ext_devset_rw_sync(io_32bit, io_32bit);
|
||||
ide_ext_devset_rw_sync(keepsettings, ksettings);
|
||||
ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
|
||||
ide_ext_devset_rw_sync(using_dma, using_dma);
|
||||
__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
|
||||
|
||||
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data;
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int ret;
|
||||
|
||||
/* Call ACPI _GTM only once */
|
||||
if (!(drive->dn % 2))
|
||||
/* call ACPI _GTM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL)
|
||||
ide_acpi_get_timing(hwif);
|
||||
|
||||
memset(&rqpm, 0, sizeof(rqpm));
|
||||
@ -382,33 +416,32 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
||||
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = ide_pm_state_start_suspend;
|
||||
rqpm.pm_step = IDE_PM_START_SUSPEND;
|
||||
if (mesg.event == PM_EVENT_PRETHAW)
|
||||
mesg.event = PM_EVENT_FREEZE;
|
||||
rqpm.pm_state = mesg.event;
|
||||
|
||||
ret = blk_execute_rq(drive->queue, NULL, rq, 0);
|
||||
blk_put_request(rq);
|
||||
/* only call ACPI _PS3 after both drivers are suspended */
|
||||
if (!ret && (((drive->dn % 2) && hwif->drives[0].present
|
||||
&& hwif->drives[1].present)
|
||||
|| !hwif->drives[0].present
|
||||
|| !hwif->drives[1].present))
|
||||
|
||||
/* call ACPI _PS3 only after both devices are suspended */
|
||||
if (ret == 0 && ((drive->dn & 1) || pair == NULL))
|
||||
ide_acpi_set_state(hwif, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int generic_ide_resume(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data;
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int err;
|
||||
|
||||
/* Call ACPI _STM only once */
|
||||
if (!(drive->dn % 2)) {
|
||||
/* call ACPI _PS0 / _STM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL) {
|
||||
ide_acpi_set_state(hwif, 1);
|
||||
ide_acpi_push_timing(hwif);
|
||||
}
|
||||
@ -422,7 +455,7 @@ static int generic_ide_resume(struct device *dev)
|
||||
rq->cmd_flags |= REQ_PREEMPT;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = ide_pm_state_start_resume;
|
||||
rqpm.pm_step = IDE_PM_START_RESUME;
|
||||
rqpm.pm_state = PM_EVENT_ON;
|
||||
|
||||
err = blk_execute_rq(drive->queue, NULL, rq, 1);
|
||||
@ -554,6 +587,7 @@ static struct device_attribute ide_dev_attrs[] = {
|
||||
__ATTR_RO(model),
|
||||
__ATTR_RO(firmware),
|
||||
__ATTR(serial, 0400, serial_show, NULL),
|
||||
__ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
@ -708,22 +742,22 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
|
||||
module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
|
||||
MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
|
||||
|
||||
static void ide_dev_apply_params(ide_drive_t *drive)
|
||||
static void ide_dev_apply_params(ide_drive_t *drive, u8 unit)
|
||||
{
|
||||
int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
|
||||
int i = drive->hwif->index * MAX_DRIVES + unit;
|
||||
|
||||
if (ide_nodma & (1 << i)) {
|
||||
printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
|
||||
drive->nodma = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NODMA;
|
||||
}
|
||||
if (ide_noflush & (1 << i)) {
|
||||
printk(KERN_INFO "ide: disabling flush requests for %s\n",
|
||||
drive->name);
|
||||
drive->noflush = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NOFLUSH;
|
||||
}
|
||||
if (ide_noprobe & (1 << i)) {
|
||||
printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
|
||||
drive->noprobe = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NOPROBE;
|
||||
}
|
||||
if (ide_nowerr & (1 << i)) {
|
||||
printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n",
|
||||
@ -732,7 +766,7 @@ static void ide_dev_apply_params(ide_drive_t *drive)
|
||||
}
|
||||
if (ide_cdroms & (1 << i)) {
|
||||
printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
|
||||
drive->present = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_PRESENT;
|
||||
drive->media = ide_cdrom;
|
||||
/* an ATAPI device ignores DRDY */
|
||||
drive->ready_stat = 0;
|
||||
@ -741,11 +775,12 @@ static void ide_dev_apply_params(ide_drive_t *drive)
|
||||
drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl;
|
||||
drive->head = drive->bios_head = ide_disks_chs[i].head;
|
||||
drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
|
||||
drive->forced_geom = 1;
|
||||
|
||||
printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
|
||||
drive->name,
|
||||
drive->cyl, drive->head, drive->sect);
|
||||
drive->present = 1;
|
||||
|
||||
drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT;
|
||||
drive->media = ide_disk;
|
||||
drive->ready_stat = ATA_DRDY;
|
||||
}
|
||||
@ -785,7 +820,7 @@ void ide_port_apply_params(ide_hwif_t *hwif)
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_DRIVES; i++)
|
||||
ide_dev_apply_params(&hwif->drives[i]);
|
||||
ide_dev_apply_params(&hwif->drives[i], i);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -131,7 +131,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
drive->name, pio, time1, time2, param1, param2, param3, param4);
|
||||
|
||||
/* stuff timing parameters into controller registers */
|
||||
driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
|
||||
driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
|
||||
spin_lock_irqsave(&ali14xx_lock, flags);
|
||||
outb_p(regOn, basePort);
|
||||
outReg(param1, regTab[driveNum].reg1);
|
||||
|
@ -120,7 +120,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
|
||||
* Need to enforce prefetch sometimes because otherwise
|
||||
* it'll hang (hard).
|
||||
*/
|
||||
if (drive->media != ide_disk || !drive->present)
|
||||
if (drive->media != ide_disk ||
|
||||
(drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
select |= HT_PREFETCH_MODE;
|
||||
|
||||
if (select != current_select || timing != current_timing) {
|
||||
@ -249,11 +250,11 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
|
||||
*/
|
||||
if (state) {
|
||||
drive->drive_data |= t; /* enable prefetch mode */
|
||||
drive->no_unmask = 1;
|
||||
drive->unmask = 0;
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
|
||||
drive->dev_flags &= ~IDE_DFLAG_UNMASK;
|
||||
} else {
|
||||
drive->drive_data &= ~t; /* disable prefetch mode */
|
||||
drive->no_unmask = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ht6560b_lock, flags);
|
||||
|
@ -14,7 +14,7 @@ MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
|
||||
static void ide_4drives_init_dev(ide_drive_t *drive)
|
||||
{
|
||||
if (drive->hwif->channel)
|
||||
drive->select.all ^= 0x20;
|
||||
drive->select ^= 0x20;
|
||||
}
|
||||
|
||||
static const struct ide_port_ops ide_4drives_port_ops = {
|
||||
|
@ -305,7 +305,7 @@ static void __init qd6580_init_dev(ide_drive_t *drive)
|
||||
} else
|
||||
t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
|
||||
|
||||
drive->drive_data = drive->select.b.unit ? t2 : t1;
|
||||
drive->drive_data = (drive->dn & 1) ? t2 : t1;
|
||||
}
|
||||
|
||||
static const struct ide_port_ops qd6500_port_ops = {
|
||||
|
@ -322,11 +322,7 @@ static int auide_dma_setup(ide_drive_t *drive)
|
||||
}
|
||||
|
||||
static int auide_dma_test_irq(ide_drive_t *drive)
|
||||
{
|
||||
if (drive->waiting_for_dma == 0)
|
||||
printk(KERN_WARNING "%s: ide_dma_test_irq \
|
||||
called while not waiting\n", drive->name);
|
||||
|
||||
{
|
||||
/* If dbdma didn't execute the STOP command yet, the
|
||||
* active bit is still set
|
||||
*/
|
||||
@ -344,11 +340,6 @@ static void auide_dma_host_set(ide_drive_t *drive, int on)
|
||||
{
|
||||
}
|
||||
|
||||
static void auide_dma_lost_irq(ide_drive_t *drive)
|
||||
{
|
||||
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
|
||||
}
|
||||
|
||||
static void auide_ddma_tx_callback(int irq, void *param)
|
||||
{
|
||||
_auide_hwif *ahwif = (_auide_hwif*)param;
|
||||
@ -375,18 +366,6 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
|
||||
static void auide_dma_timeout(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
||||
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
|
||||
|
||||
if (auide_dma_test_irq(drive))
|
||||
return;
|
||||
|
||||
auide_dma_end(drive);
|
||||
}
|
||||
|
||||
static const struct ide_dma_ops au1xxx_dma_ops = {
|
||||
.dma_host_set = auide_dma_host_set,
|
||||
.dma_setup = auide_dma_setup,
|
||||
@ -394,8 +373,8 @@ static const struct ide_dma_ops au1xxx_dma_ops = {
|
||||
.dma_start = auide_dma_start,
|
||||
.dma_end = auide_dma_end,
|
||||
.dma_test_irq = auide_dma_test_irq,
|
||||
.dma_lost_irq = auide_dma_lost_irq,
|
||||
.dma_timeout = auide_dma_timeout,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
};
|
||||
|
||||
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
|
||||
@ -448,10 +427,9 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
|
||||
NUM_DESCRIPTORS);
|
||||
auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
|
||||
NUM_DESCRIPTORS);
|
||||
|
||||
hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
|
||||
PRD_ENTRIES * PRD_BYTES, /* 1 Page */
|
||||
&hwif->dmatable_dma, GFP_KERNEL);
|
||||
|
||||
/* FIXME: check return value */
|
||||
(void)ide_allocate_dma_engine(hwif);
|
||||
|
||||
au1xxx_dbdma_start( auide->tx_chan );
|
||||
au1xxx_dbdma_start( auide->rx_chan );
|
||||
|
@ -115,7 +115,7 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct ide_host *host = pci_get_drvdata(dev);
|
||||
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 unit = drive->dn & 1;
|
||||
u8 tmp1 = 0, tmp2 = 0;
|
||||
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
|
||||
unsigned long flags;
|
||||
@ -302,7 +302,7 @@ static const struct pci_device_id aec62xx_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver aec62xx_pci_driver = {
|
||||
.name = "AEC62xx_IDE",
|
||||
.id_table = aec62xx_pci_tbl,
|
||||
.probe = aec62xx_init_one,
|
||||
@ -313,12 +313,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init aec62xx_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&aec62xx_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit aec62xx_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&aec62xx_pci_driver);
|
||||
}
|
||||
|
||||
module_init(aec62xx_ide_init);
|
||||
|
@ -77,8 +77,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
int port = hwif->channel ? 0x5c : 0x58;
|
||||
int portFIFO = hwif->channel ? 0x55 : 0x54;
|
||||
u8 cd_dma_fifo = 0;
|
||||
int unit = drive->select.b.unit & 1;
|
||||
u8 cd_dma_fifo = 0, unit = drive->dn & 1;
|
||||
|
||||
if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
|
||||
s_clc = 0;
|
||||
@ -112,7 +111,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, port, s_clc);
|
||||
pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
|
||||
pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
@ -154,7 +153,7 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u8 speed1 = speed;
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 unit = drive->dn & 1;
|
||||
u8 tmpbyte = 0x00;
|
||||
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
|
||||
|
||||
@ -508,7 +507,7 @@ static const struct ide_dma_ops ali_dma_ops = {
|
||||
.dma_setup = ali15x3_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = ide_dma_test_irq,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
@ -576,7 +575,7 @@ static const struct pci_device_id alim15x3_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver alim15x3_pci_driver = {
|
||||
.name = "ALI15x3_IDE",
|
||||
.id_table = alim15x3_pci_tbl,
|
||||
.probe = alim15x3_init_one,
|
||||
@ -587,12 +586,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init ali15x3_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&alim15x3_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit ali15x3_ide_exit(void)
|
||||
{
|
||||
return pci_unregister_driver(&driver);
|
||||
return pci_unregister_driver(&alim15x3_pci_driver);
|
||||
}
|
||||
|
||||
module_init(ali15x3_ide_init);
|
||||
|
@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
|
||||
|
||||
ide_timing_compute(drive, speed, &t, T, UT);
|
||||
|
||||
if (peer->present) {
|
||||
if (peer->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
|
||||
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
|
||||
}
|
||||
@ -319,7 +319,7 @@ static const struct pci_device_id amd74xx_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver amd74xx_pci_driver = {
|
||||
.name = "AMD_IDE",
|
||||
.id_table = amd74xx_pci_tbl,
|
||||
.probe = amd74xx_probe,
|
||||
@ -330,12 +330,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init amd74xx_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&amd74xx_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit amd74xx_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&amd74xx_pci_driver);
|
||||
}
|
||||
|
||||
module_init(amd74xx_ide_init);
|
||||
|
@ -182,7 +182,7 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver atiixp_pci_driver = {
|
||||
.name = "ATIIXP_IDE",
|
||||
.id_table = atiixp_pci_tbl,
|
||||
.probe = atiixp_init_one,
|
||||
@ -193,12 +193,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init atiixp_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&atiixp_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit atiixp_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&atiixp_pci_driver);
|
||||
}
|
||||
|
||||
module_init(atiixp_ide_init);
|
||||
|
@ -378,13 +378,13 @@ static void __set_prefetch_mode(ide_drive_t *drive, int mode)
|
||||
{
|
||||
if (mode) { /* want prefetch on? */
|
||||
#if CMD640_PREFETCH_MASKS
|
||||
drive->no_unmask = 1;
|
||||
drive->unmask = 0;
|
||||
drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
|
||||
drive->dev_flags &= ~IDE_DFLAG_UNMASK;
|
||||
#endif
|
||||
drive->no_io_32bit = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
|
||||
} else {
|
||||
drive->no_unmask = 0;
|
||||
drive->no_io_32bit = 1;
|
||||
drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
|
||||
drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
|
||||
drive->io_32bit = 0;
|
||||
}
|
||||
}
|
||||
@ -468,10 +468,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
|
||||
*/
|
||||
if (index > 1) {
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
|
||||
ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
|
||||
unsigned int mate = index ^ 1;
|
||||
|
||||
if (peer->present) {
|
||||
if (peer->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
if (setup_count < setup_counts[mate])
|
||||
setup_count = setup_counts[mate];
|
||||
if (active_count < active_counts[mate])
|
||||
@ -607,7 +607,7 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
|
||||
static void cmd640_init_dev(ide_drive_t *drive)
|
||||
{
|
||||
unsigned int i = drive->hwif->channel * 2 + drive->select.b.unit;
|
||||
unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
|
||||
/*
|
||||
@ -626,7 +626,7 @@ static void cmd640_init_dev(ide_drive_t *drive)
|
||||
*/
|
||||
check_prefetch(drive, i);
|
||||
printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
|
||||
i, drive->no_io_32bit ? "off" : "on");
|
||||
i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
|
||||
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ static int cmd648_dma_end(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long base = hwif->dma_base - (hwif->channel * 8);
|
||||
int err = __ide_dma_end(drive);
|
||||
int err = ide_dma_end(drive);
|
||||
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
|
||||
MRDMODE_INTR_CH0;
|
||||
u8 mrdmode = inb(base + 1);
|
||||
@ -248,7 +248,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
|
||||
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
|
||||
CFR_INTR_CH0;
|
||||
u8 irq_stat = 0;
|
||||
int err = __ide_dma_end(drive);
|
||||
int err = ide_dma_end(drive);
|
||||
|
||||
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
|
||||
/* clear the interrupt bit */
|
||||
@ -505,7 +505,7 @@ static const struct pci_device_id cmd64x_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver cmd64x_pci_driver = {
|
||||
.name = "CMD64x_IDE",
|
||||
.id_table = cmd64x_pci_tbl,
|
||||
.probe = cmd64x_init_one,
|
||||
@ -516,12 +516,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init cmd64x_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&cmd64x_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit cmd64x_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&cmd64x_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cmd64x_ide_init);
|
||||
|
@ -145,7 +145,7 @@ static const struct pci_device_id cs5520_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver cs5520_pci_driver = {
|
||||
.name = "Cyrix_IDE",
|
||||
.id_table = cs5520_pci_tbl,
|
||||
.probe = cs5520_init_one,
|
||||
@ -155,7 +155,7 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init cs5520_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&cs5520_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cs5520_ide_init);
|
||||
|
@ -267,7 +267,7 @@ static const struct pci_device_id cs5530_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver cs5530_pci_driver = {
|
||||
.name = "CS5530 IDE",
|
||||
.id_table = cs5530_pci_tbl,
|
||||
.probe = cs5530_init_one,
|
||||
@ -278,12 +278,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init cs5530_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&cs5530_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit cs5530_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&cs5530_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cs5530_ide_init);
|
||||
|
@ -76,7 +76,7 @@ static unsigned int cs5535_udma_timings[5] =
|
||||
static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
u32 reg = 0, dummy;
|
||||
int unit = drive->select.b.unit;
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
/* Set the PIO timings */
|
||||
if (speed < XFER_SW_DMA_0) {
|
||||
@ -192,7 +192,7 @@ static const struct pci_device_id cs5535_pci_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver cs5535_pci_driver = {
|
||||
.name = "CS5535_IDE",
|
||||
.id_table = cs5535_pci_tbl,
|
||||
.probe = cs5535_init_one,
|
||||
@ -203,12 +203,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init cs5535_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&cs5535_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit cs5535_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&cs5535_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cs5535_ide_init);
|
||||
|
@ -50,18 +50,11 @@
|
||||
|
||||
#define DRV_NAME "cy82c693"
|
||||
|
||||
/* the current version */
|
||||
#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
|
||||
|
||||
/*
|
||||
* The following are used to debug the driver.
|
||||
*/
|
||||
#define CY82C693_DEBUG_LOGS 0
|
||||
#define CY82C693_DEBUG_INFO 0
|
||||
|
||||
/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
|
||||
#undef CY82C693_SETDMA_CLOCK
|
||||
|
||||
/*
|
||||
* NOTE: the value for busmaster timeout is tricky and I got it by
|
||||
* trial and error! By using a to low value will cause DMA timeouts
|
||||
@ -89,7 +82,6 @@
|
||||
#define CY82_INDEX_PORT 0x22
|
||||
#define CY82_DATA_PORT 0x23
|
||||
|
||||
#define CY82_INDEX_CTRLREG1 0x01
|
||||
#define CY82_INDEX_CHANNEL0 0x30
|
||||
#define CY82_INDEX_CHANNEL1 0x31
|
||||
#define CY82_INDEX_TIMEOUT 0x32
|
||||
@ -179,17 +171,6 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
|
||||
index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
|
||||
|
||||
#if CY82C693_DEBUG_LOGS
|
||||
/* for debug let's show the previous values */
|
||||
|
||||
outb(index, CY82_INDEX_PORT);
|
||||
data = inb(CY82_DATA_PORT);
|
||||
|
||||
printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
|
||||
drive->name, HWIF(drive)->channel, drive->select.b.unit,
|
||||
(data&0x3), ((data>>2)&1));
|
||||
#endif /* CY82C693_DEBUG_LOGS */
|
||||
|
||||
data = (mode & 3) | (single << 2);
|
||||
|
||||
outb(index, CY82_INDEX_PORT);
|
||||
@ -197,8 +178,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
|
||||
#if CY82C693_DEBUG_INFO
|
||||
printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
|
||||
drive->name, HWIF(drive)->channel, drive->select.b.unit,
|
||||
mode & 3, single);
|
||||
drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
|
||||
#endif /* CY82C693_DEBUG_INFO */
|
||||
|
||||
/*
|
||||
@ -239,50 +219,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
}
|
||||
}
|
||||
|
||||
#if CY82C693_DEBUG_LOGS
|
||||
/* for debug let's show the register values */
|
||||
|
||||
if (drive->select.b.unit == 0) {
|
||||
/*
|
||||
* get master drive registers
|
||||
* address setup control register
|
||||
* is 32 bit !!!
|
||||
*/
|
||||
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
|
||||
addrCtrl &= 0x0F;
|
||||
|
||||
/* now let's get the remaining registers */
|
||||
pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
|
||||
pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
|
||||
pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
|
||||
} else {
|
||||
/*
|
||||
* set slave drive registers
|
||||
* address setup control register
|
||||
* is 32 bit !!!
|
||||
*/
|
||||
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
|
||||
|
||||
addrCtrl &= 0xF0;
|
||||
addrCtrl >>= 4;
|
||||
|
||||
/* now let's get the remaining registers */
|
||||
pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
|
||||
pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
|
||||
pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is "
|
||||
"(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
|
||||
drive->name, hwif->channel, drive->select.b.unit,
|
||||
addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
|
||||
#endif /* CY82C693_DEBUG_LOGS */
|
||||
|
||||
/* let's calc the values for this PIO mode */
|
||||
compute_clocks(pio, &pclk);
|
||||
|
||||
/* now let's write the clocks registers */
|
||||
if (drive->select.b.unit == 0) {
|
||||
if ((drive->dn & 1) == 0) {
|
||||
/*
|
||||
* set master drive
|
||||
* address setup control register
|
||||
@ -324,63 +265,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
#if CY82C693_DEBUG_INFO
|
||||
printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
|
||||
"(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
|
||||
drive->name, hwif->channel, drive->select.b.unit,
|
||||
drive->name, hwif->channel, drive->dn & 1,
|
||||
addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
|
||||
#endif /* CY82C693_DEBUG_INFO */
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is called during init and is used to setup the cy82c693 chip
|
||||
*/
|
||||
static unsigned int init_chipset_cy82c693(struct pci_dev *dev)
|
||||
{
|
||||
if (PCI_FUNC(dev->devfn) != 1)
|
||||
return 0;
|
||||
|
||||
#ifdef CY82C693_SETDMA_CLOCK
|
||||
u8 data = 0;
|
||||
#endif /* CY82C693_SETDMA_CLOCK */
|
||||
|
||||
/* write info about this verion of the driver */
|
||||
printk(KERN_INFO CY82_VERSION "\n");
|
||||
|
||||
#ifdef CY82C693_SETDMA_CLOCK
|
||||
/* okay let's set the DMA clock speed */
|
||||
|
||||
outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
|
||||
data = inb(CY82_DATA_PORT);
|
||||
|
||||
#if CY82C693_DEBUG_INFO
|
||||
printk(KERN_INFO DRV_NAME ": Peripheral Configuration Register: 0x%X\n",
|
||||
data);
|
||||
#endif /* CY82C693_DEBUG_INFO */
|
||||
|
||||
/*
|
||||
* for some reason sometimes the DMA controller
|
||||
* speed is set to ATCLK/2 ???? - we fix this here
|
||||
*
|
||||
* note: i don't know what causes this strange behaviour,
|
||||
* but even changing the dma speed doesn't solve it :-(
|
||||
* the ide performance is still only half the normal speed
|
||||
*
|
||||
* if anybody knows what goes wrong with my machine, please
|
||||
* let me know - ASK
|
||||
*/
|
||||
|
||||
data |= 0x03;
|
||||
|
||||
outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
|
||||
outb(data, CY82_DATA_PORT);
|
||||
|
||||
#if CY82C693_DEBUG_INFO
|
||||
printk(KERN_INFO ": New Peripheral Configuration Register: 0x%X\n",
|
||||
data);
|
||||
#endif /* CY82C693_DEBUG_INFO */
|
||||
|
||||
#endif /* CY82C693_SETDMA_CLOCK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
|
||||
{
|
||||
static ide_hwif_t *primary;
|
||||
@ -401,7 +290,6 @@ static const struct ide_port_ops cy82c693_port_ops = {
|
||||
|
||||
static const struct ide_port_info cy82c693_chipset __devinitdata = {
|
||||
.name = DRV_NAME,
|
||||
.init_chipset = init_chipset_cy82c693,
|
||||
.init_iops = init_iops_cy82c693,
|
||||
.port_ops = &cy82c693_port_ops,
|
||||
.chipset = ide_cy82c693,
|
||||
@ -443,7 +331,7 @@ static const struct pci_device_id cy82c693_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver cy82c693_pci_driver = {
|
||||
.name = "Cypress_IDE",
|
||||
.id_table = cy82c693_pci_tbl,
|
||||
.probe = cy82c693_init_one,
|
||||
@ -454,12 +342,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init cy82c693_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&cy82c693_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit cy82c693_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&cy82c693_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cy82c693_ide_init);
|
||||
|
@ -117,7 +117,7 @@ static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver delkin_cb_pci_driver = {
|
||||
.name = "Delkin-ASKA-Workbit Cardbus IDE",
|
||||
.id_table = delkin_cb_pci_tbl,
|
||||
.probe = delkin_cb_probe,
|
||||
@ -126,12 +126,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init delkin_cb_init(void)
|
||||
{
|
||||
return pci_register_driver(&driver);
|
||||
return pci_register_driver(&delkin_cb_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit delkin_cb_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&delkin_cb_pci_driver);
|
||||
}
|
||||
|
||||
module_init(delkin_cb_init);
|
||||
|
@ -166,7 +166,7 @@ static const struct pci_device_id generic_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver generic_pci_driver = {
|
||||
.name = "PCI_IDE",
|
||||
.id_table = generic_pci_tbl,
|
||||
.probe = generic_init_one,
|
||||
@ -177,12 +177,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init generic_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&generic_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit generic_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&generic_pci_driver);
|
||||
}
|
||||
|
||||
module_init(generic_ide_init);
|
||||
|
@ -166,7 +166,7 @@ static const struct pci_device_id hpt34x_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver hpt34x_pci_driver = {
|
||||
.name = "HPT34x_IDE",
|
||||
.id_table = hpt34x_pci_tbl,
|
||||
.probe = hpt34x_init_one,
|
||||
@ -177,12 +177,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init hpt34x_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&hpt34x_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit hpt34x_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&hpt34x_pci_driver);
|
||||
}
|
||||
|
||||
module_init(hpt34x_ide_init);
|
||||
|
@ -835,7 +835,7 @@ static int hpt370_dma_end(ide_drive_t *drive)
|
||||
if (dma_stat & 0x01)
|
||||
hpt370_irq_timeout(drive);
|
||||
}
|
||||
return __ide_dma_end(drive);
|
||||
return ide_dma_end(drive);
|
||||
}
|
||||
|
||||
static void hpt370_dma_timeout(ide_drive_t *drive)
|
||||
@ -863,9 +863,6 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
|
||||
if (dma_stat & 4)
|
||||
return 1;
|
||||
|
||||
if (!drive->waiting_for_dma)
|
||||
printk(KERN_WARNING "%s: (%s) called while not waiting\n",
|
||||
drive->name, __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -880,7 +877,7 @@ static int hpt374_dma_end(ide_drive_t *drive)
|
||||
pci_read_config_byte(dev, mcr_addr, &mcr);
|
||||
if (bwsr & mask)
|
||||
pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
|
||||
return __ide_dma_end(drive);
|
||||
return ide_dma_end(drive);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1456,7 +1453,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = ide_dma_test_irq,
|
||||
.dma_lost_irq = hpt366_dma_lost_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
@ -1622,7 +1619,7 @@ static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver hpt366_pci_driver = {
|
||||
.name = "HPT366_IDE",
|
||||
.id_table = hpt366_pci_tbl,
|
||||
.probe = hpt366_init_one,
|
||||
@ -1633,12 +1630,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init hpt366_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&hpt366_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit hpt366_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&hpt366_pci_driver);
|
||||
}
|
||||
|
||||
module_init(hpt366_ide_init);
|
||||
|
@ -189,7 +189,7 @@ static const struct pci_device_id it8213_pci_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver it8213_pci_driver = {
|
||||
.name = "ITE8213_IDE",
|
||||
.id_table = it8213_pci_tbl,
|
||||
.probe = it8213_init_one,
|
||||
@ -200,12 +200,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init it8213_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&it8213_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit it8213_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&it8213_pci_driver);
|
||||
}
|
||||
|
||||
module_init(it8213_ide_init);
|
||||
|
@ -138,8 +138,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
int channel = hwif->channel;
|
||||
int unit = drive->select.b.unit;
|
||||
u8 conf;
|
||||
u8 unit = drive->dn & 1, conf;
|
||||
|
||||
/* Program UDMA timing bits */
|
||||
if(itdev->clock_mode == ATA_66)
|
||||
@ -168,13 +167,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
ide_drive_t *pair;
|
||||
int clock, altclock, sel = 0;
|
||||
u8 unit = drive->dn & 1, v;
|
||||
|
||||
u8 unit = drive->select.b.unit;
|
||||
ide_drive_t *pair = &hwif->drives[1-unit];
|
||||
|
||||
int clock, altclock;
|
||||
u8 v;
|
||||
int sel = 0;
|
||||
pair = &hwif->drives[1 - unit];
|
||||
|
||||
if(itdev->want[0][0] > itdev->want[1][0]) {
|
||||
clock = itdev->want[0][1];
|
||||
@ -240,16 +237,17 @@ static void it821x_clock_strategy(ide_drive_t *drive)
|
||||
|
||||
static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
int unit = drive->select.b.unit;
|
||||
ide_drive_t *pair = &hwif->drives[1 - unit];
|
||||
u8 set_pio = pio;
|
||||
ide_drive_t *pair;
|
||||
u8 unit = drive->dn & 1, set_pio = pio;
|
||||
|
||||
/* Spec says 89 ref driver uses 88 */
|
||||
static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
|
||||
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
|
||||
|
||||
pair = &hwif->drives[1 - unit];
|
||||
|
||||
/*
|
||||
* Compute the best PIO mode we can for a given device. We must
|
||||
* pick a speed that does not cause problems with the other device
|
||||
@ -286,9 +284,7 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
|
||||
int unit = drive->select.b.unit;
|
||||
int channel = hwif->channel;
|
||||
u8 conf;
|
||||
u8 unit = drive->dn & 1, channel = hwif->channel, conf;
|
||||
|
||||
static u16 dma[] = { 0x8866, 0x3222, 0x3121 };
|
||||
static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY };
|
||||
@ -325,9 +321,7 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
int unit = drive->select.b.unit;
|
||||
int channel = hwif->channel;
|
||||
u8 conf;
|
||||
u8 unit = drive->dn & 1, channel = hwif->channel, conf;
|
||||
|
||||
static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
|
||||
static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
|
||||
@ -369,7 +363,8 @@ static void it821x_dma_start(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
int unit = drive->select.b.unit;
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
if(itdev->mwdma[unit] != MWDMA_OFF)
|
||||
it821x_program(drive, itdev->mwdma[unit]);
|
||||
else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
|
||||
@ -389,9 +384,10 @@ static void it821x_dma_start(ide_drive_t *drive)
|
||||
static int it821x_dma_end(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int unit = drive->select.b.unit;
|
||||
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
|
||||
int ret = __ide_dma_end(drive);
|
||||
int ret = ide_dma_end(drive);
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
if(itdev->mwdma[unit] != MWDMA_OFF)
|
||||
it821x_program(drive, itdev->pio[unit]);
|
||||
return ret;
|
||||
@ -454,7 +450,7 @@ static void it821x_quirkproc(ide_drive_t *drive)
|
||||
* IRQ mask as we may well be in PIO (eg rev 0x10)
|
||||
* for now and we know unmasking is safe on this chipset.
|
||||
*/
|
||||
drive->unmask = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_UNMASK;
|
||||
} else {
|
||||
/*
|
||||
* Perform fixups on smart mode. We need to "lose" some
|
||||
@ -680,7 +676,7 @@ static const struct pci_device_id it821x_pci_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver it821x_pci_driver = {
|
||||
.name = "ITE821x IDE",
|
||||
.id_table = it821x_pci_tbl,
|
||||
.probe = it821x_init_one,
|
||||
@ -691,12 +687,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init it821x_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&it821x_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit it821x_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&it821x_pci_driver);
|
||||
}
|
||||
|
||||
module_init(it821x_ide_init);
|
||||
|
@ -149,7 +149,7 @@ static struct pci_device_id jmicron_pci_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver jmicron_pci_driver = {
|
||||
.name = "JMicron IDE",
|
||||
.id_table = jmicron_pci_tbl,
|
||||
.probe = jmicron_init_one,
|
||||
@ -160,12 +160,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init jmicron_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&jmicron_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit jmicron_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&jmicron_pci_driver);
|
||||
}
|
||||
|
||||
module_init(jmicron_ide_init);
|
||||
|
@ -137,7 +137,7 @@ static void __devinit superio_init_iops(struct hwif_s *hwif)
|
||||
static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
|
||||
|
||||
/*
|
||||
* This routine either enables/disables (according to drive->present)
|
||||
* This routine either enables/disables (according to IDE_DFLAG_PRESENT)
|
||||
* the IRQ associated with the port (HWIF(drive)),
|
||||
* and selects either PIO or DMA handshaking for the next I/O operation.
|
||||
*/
|
||||
@ -153,11 +153,15 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
|
||||
|
||||
/* Adjust IRQ enable bit */
|
||||
bit = 1 << (8 + hwif->channel);
|
||||
new = drive->present ? (new & ~bit) : (new | bit);
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT)
|
||||
new &= ~bit;
|
||||
else
|
||||
new |= bit;
|
||||
|
||||
/* Select PIO or DMA, DMA may only be selected for one drive/channel. */
|
||||
bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
|
||||
other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
|
||||
bit = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
|
||||
other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
|
||||
new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
|
||||
|
||||
if (new != *old) {
|
||||
@ -187,7 +191,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
|
||||
|
||||
static void ns87415_selectproc (ide_drive_t *drive)
|
||||
{
|
||||
ns87415_prepare_drive (drive, drive->using_dma);
|
||||
ns87415_prepare_drive(drive,
|
||||
!!(drive->dev_flags & IDE_DFLAG_USING_DMA));
|
||||
}
|
||||
|
||||
static int ns87415_dma_end(ide_drive_t *drive)
|
||||
@ -334,7 +339,7 @@ static const struct pci_device_id ns87415_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver ns87415_pci_driver = {
|
||||
.name = "NS87415_IDE",
|
||||
.id_table = ns87415_pci_tbl,
|
||||
.probe = ns87415_init_one,
|
||||
@ -345,12 +350,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init ns87415_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&ns87415_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit ns87415_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&ns87415_pci_driver);
|
||||
}
|
||||
|
||||
module_init(ns87415_ide_init);
|
||||
|
@ -179,7 +179,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
misc = addr_timings[clk][addr_pio];
|
||||
|
||||
/* select Index-0/1 for Register-A/B */
|
||||
write_reg(drive->select.b.unit, MISC_REG);
|
||||
write_reg(drive->dn & 1, MISC_REG);
|
||||
/* set read cycle timings */
|
||||
write_reg(tim, READ_REG);
|
||||
/* set write cycle timings */
|
||||
@ -220,7 +220,7 @@ static const struct pci_device_id opti621_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver opti621_pci_driver = {
|
||||
.name = "Opti621_IDE",
|
||||
.id_table = opti621_pci_tbl,
|
||||
.probe = opti621_init_one,
|
||||
@ -231,12 +231,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init opti621_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&opti621_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit opti621_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&opti621_pci_driver);
|
||||
}
|
||||
|
||||
module_init(opti621_ide_init);
|
||||
|
@ -561,7 +561,7 @@ static const struct pci_device_id pdc202new_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver pdc202new_pci_driver = {
|
||||
.name = "Promise_IDE",
|
||||
.id_table = pdc202new_pci_tbl,
|
||||
.probe = pdc202new_init_one,
|
||||
@ -572,12 +572,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init pdc202new_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&pdc202new_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit pdc202new_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&pdc202new_pci_driver);
|
||||
}
|
||||
|
||||
module_init(pdc202new_ide_init);
|
||||
|
@ -168,7 +168,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
|
||||
{
|
||||
if (drive->current_speed > XFER_UDMA_2)
|
||||
pdc_old_enable_66MHz_clock(drive->hwif);
|
||||
if (drive->media != ide_disk || drive->addressing == 1) {
|
||||
if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
@ -188,7 +188,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
|
||||
|
||||
static int pdc202xx_dma_end(ide_drive_t *drive)
|
||||
{
|
||||
if (drive->media != ide_disk || drive->addressing == 1) {
|
||||
if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
|
||||
@ -200,7 +200,7 @@ static int pdc202xx_dma_end(ide_drive_t *drive)
|
||||
}
|
||||
if (drive->current_speed > XFER_UDMA_2)
|
||||
pdc_old_disable_66MHz_clock(drive->hwif);
|
||||
return __ide_dma_end(drive);
|
||||
return ide_dma_end(drive);
|
||||
}
|
||||
|
||||
static int pdc202xx_dma_test_irq(ide_drive_t *drive)
|
||||
@ -333,7 +333,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = {
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = pdc202xx_dma_test_irq,
|
||||
.dma_lost_irq = pdc202xx_dma_lost_irq,
|
||||
.dma_timeout = pdc202xx_dma_timeout,
|
||||
@ -426,7 +426,7 @@ static const struct pci_device_id pdc202xx_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver pdc202xx_pci_driver = {
|
||||
.name = "Promise_Old_IDE",
|
||||
.id_table = pdc202xx_pci_tbl,
|
||||
.probe = pdc202xx_init_one,
|
||||
@ -437,12 +437,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init pdc202xx_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&pdc202xx_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit pdc202xx_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&pdc202xx_pci_driver);
|
||||
}
|
||||
|
||||
module_init(pdc202xx_ide_init);
|
||||
|
@ -215,17 +215,26 @@ static unsigned int init_chipset_ich(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_dma_clear_irq - clear BMDMA status
|
||||
* @drive: IDE drive to clear
|
||||
* ich_clear_irq - clear BMDMA status
|
||||
* @drive: IDE drive
|
||||
*
|
||||
* Called from ide_intr() for PIO interrupts
|
||||
* to clear BMDMA status as needed by ICHx
|
||||
* ICHx contollers set DMA INTR no matter DMA or PIO.
|
||||
* BMDMA status might need to be cleared even for
|
||||
* PIO interrupts to prevent spurious/lost IRQ.
|
||||
*/
|
||||
static void piix_dma_clear_irq(ide_drive_t *drive)
|
||||
static void ich_clear_irq(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 dma_stat;
|
||||
|
||||
/*
|
||||
* ide_dma_end() needs BMDMA status for error checking.
|
||||
* So, skip clearing BMDMA status here and leave it
|
||||
* to ide_dma_end() if this is DMA interrupt.
|
||||
*/
|
||||
if (drive->waiting_for_dma || hwif->dma_base == 0)
|
||||
return;
|
||||
|
||||
/* clear the INTR & ERROR bits */
|
||||
dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
|
||||
/* Should we force the bit as well ? */
|
||||
@ -249,6 +258,7 @@ static const struct ich_laptop ich_laptop[] = {
|
||||
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
|
||||
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
|
||||
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
|
||||
{ 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
|
||||
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
|
||||
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
|
||||
/* end marker */
|
||||
@ -293,21 +303,19 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
|
||||
hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
|
||||
}
|
||||
|
||||
static void __devinit init_hwif_ich(ide_hwif_t *hwif)
|
||||
{
|
||||
init_hwif_piix(hwif);
|
||||
|
||||
/* ICHx need to clear the BMDMA status for all interrupts */
|
||||
if (hwif->dma_base)
|
||||
hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
|
||||
}
|
||||
|
||||
static const struct ide_port_ops piix_port_ops = {
|
||||
.set_pio_mode = piix_set_pio_mode,
|
||||
.set_dma_mode = piix_set_dma_mode,
|
||||
.cable_detect = piix_cable_detect,
|
||||
};
|
||||
|
||||
static const struct ide_port_ops ich_port_ops = {
|
||||
.set_pio_mode = piix_set_pio_mode,
|
||||
.set_dma_mode = piix_set_dma_mode,
|
||||
.clear_irq = ich_clear_irq,
|
||||
.cable_detect = piix_cable_detect,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_IA64
|
||||
#define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
|
||||
#else
|
||||
@ -331,9 +339,9 @@ static const struct ide_port_ops piix_port_ops = {
|
||||
{ \
|
||||
.name = DRV_NAME, \
|
||||
.init_chipset = init_chipset_ich, \
|
||||
.init_hwif = init_hwif_ich, \
|
||||
.init_hwif = init_hwif_piix, \
|
||||
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
|
||||
.port_ops = &piix_port_ops, \
|
||||
.port_ops = &ich_port_ops, \
|
||||
.host_flags = IDE_HFLAGS_PIIX, \
|
||||
.pio_mask = ATA_PIO4, \
|
||||
.swdma_mask = ATA_SWDMA2_ONLY, \
|
||||
@ -444,7 +452,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver piix_pci_driver = {
|
||||
.name = "PIIX_IDE",
|
||||
.id_table = piix_pci_tbl,
|
||||
.probe = piix_init_one,
|
||||
@ -456,12 +464,12 @@ static struct pci_driver driver = {
|
||||
static int __init piix_ide_init(void)
|
||||
{
|
||||
piix_check_450nx();
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&piix_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit piix_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&piix_pci_driver);
|
||||
}
|
||||
|
||||
module_init(piix_ide_init);
|
||||
|
@ -59,7 +59,7 @@ static const struct pci_device_id rz1000_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver rz1000_pci_driver = {
|
||||
.name = "RZ1000_IDE",
|
||||
.id_table = rz1000_pci_tbl,
|
||||
.probe = rz1000_init_one,
|
||||
@ -68,12 +68,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init rz1000_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&rz1000_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit rz1000_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&rz1000_pci_driver);
|
||||
}
|
||||
|
||||
module_init(rz1000_ide_init);
|
||||
|
@ -126,7 +126,6 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
int unit = drive->select.b.unit;
|
||||
unsigned int reg, timings;
|
||||
unsigned short pci_clock;
|
||||
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
|
||||
@ -155,7 +154,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
else
|
||||
timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
|
||||
|
||||
if (unit == 0) { /* are we configuring drive0? */
|
||||
if ((drive->dn & 1) == 0) {
|
||||
pci_read_config_dword(dev, basereg + 4, ®);
|
||||
timings |= reg & 0x80000000; /* preserve PIO format bit */
|
||||
pci_write_config_dword(dev, basereg + 4, timings);
|
||||
@ -216,7 +215,8 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
if (mode != -1) {
|
||||
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
|
||||
ide_dma_off_quietly(drive);
|
||||
if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
|
||||
if (ide_set_dma_mode(drive, mode) == 0 &&
|
||||
(drive->dev_flags & IDE_DFLAG_USING_DMA))
|
||||
hwif->dma_ops->dma_host_set(drive, 1);
|
||||
return;
|
||||
}
|
||||
@ -328,7 +328,7 @@ static const struct pci_device_id sc1200_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver sc1200_pci_driver = {
|
||||
.name = "SC1200_IDE",
|
||||
.id_table = sc1200_pci_tbl,
|
||||
.probe = sc1200_init_one,
|
||||
@ -341,12 +341,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init sc1200_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&sc1200_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit sc1200_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&sc1200_pci_driver);
|
||||
}
|
||||
|
||||
module_init(sc1200_ide_init);
|
||||
|
@ -291,7 +291,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void scc_dma_host_set(ide_drive_t *drive, int on)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 unit = drive->dn & 1;
|
||||
u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
|
||||
|
||||
if (on)
|
||||
@ -353,7 +353,6 @@ static void scc_dma_start(ide_drive_t *drive)
|
||||
|
||||
/* start DMA */
|
||||
scc_ide_outb(dma_cmd | 1, hwif->dma_base);
|
||||
hwif->dma = 1;
|
||||
wmb();
|
||||
}
|
||||
|
||||
@ -374,7 +373,6 @@ static int __scc_dma_end(ide_drive_t *drive)
|
||||
/* purge DMA mappings */
|
||||
ide_destroy_dmatable(drive);
|
||||
/* verify good DMA status */
|
||||
hwif->dma = 0;
|
||||
wmb();
|
||||
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
|
||||
}
|
||||
@ -511,9 +509,6 @@ static int scc_dma_test_irq(ide_drive_t *drive)
|
||||
if (int_stat & INTSTS_IOIRQS)
|
||||
return 1;
|
||||
|
||||
if (!drive->waiting_for_dma)
|
||||
printk(KERN_WARNING "%s: (%s) called while not waiting\n",
|
||||
drive->name, __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -710,7 +705,7 @@ static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
|
||||
scc_ide_outb(tf->lbah, io_ports->lbah_addr);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
|
||||
scc_ide_outb((tf->device & HIHI) | drive->select.all,
|
||||
scc_ide_outb((tf->device & HIHI) | drive->select,
|
||||
io_ports->device_addr);
|
||||
}
|
||||
|
||||
@ -826,6 +821,12 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
|
||||
init_mmio_iops_scc(hwif);
|
||||
}
|
||||
|
||||
static int __devinit scc_init_dma(ide_hwif_t *hwif,
|
||||
const struct ide_port_info *d)
|
||||
{
|
||||
return ide_allocate_dma_engine(hwif);
|
||||
}
|
||||
|
||||
static u8 scc_cable_detect(ide_hwif_t *hwif)
|
||||
{
|
||||
return ATA_CBL_PATA80;
|
||||
@ -890,6 +891,7 @@ static const struct ide_dma_ops scc_dma_ops = {
|
||||
{ \
|
||||
.name = name_str, \
|
||||
.init_iops = init_iops_scc, \
|
||||
.init_dma = scc_init_dma, \
|
||||
.init_hwif = init_hwif_scc, \
|
||||
.tp_ops = &scc_tp_ops, \
|
||||
.port_ops = &scc_port_ops, \
|
||||
@ -927,13 +929,6 @@ static void __devexit scc_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct scc_ports *ports = pci_get_drvdata(dev);
|
||||
struct ide_host *host = ports->host;
|
||||
ide_hwif_t *hwif = host->ports[0];
|
||||
|
||||
if (hwif->dmatable_cpu) {
|
||||
pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
|
||||
hwif->dmatable_cpu, hwif->dmatable_dma);
|
||||
hwif->dmatable_cpu = NULL;
|
||||
}
|
||||
|
||||
ide_host_remove(host);
|
||||
|
||||
@ -949,7 +944,7 @@ static const struct pci_device_id scc_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver scc_pci_driver = {
|
||||
.name = "SCC IDE",
|
||||
.id_table = scc_pci_tbl,
|
||||
.probe = scc_init_one,
|
||||
@ -958,14 +953,14 @@ static struct pci_driver driver = {
|
||||
|
||||
static int scc_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&scc_pci_driver);
|
||||
}
|
||||
|
||||
module_init(scc_ide_init);
|
||||
/* -- No exit code?
|
||||
static void scc_ide_exit(void)
|
||||
{
|
||||
ide_pci_unregister_driver(&driver);
|
||||
ide_pci_unregister_driver(&scc_pci_driver);
|
||||
}
|
||||
module_exit(scc_ide_exit);
|
||||
*/
|
||||
|
@ -153,7 +153,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
|
||||
|
||||
@ -443,7 +443,7 @@ static const struct pci_device_id svwks_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver svwks_pci_driver = {
|
||||
.name = "Serverworks_IDE",
|
||||
.id_table = svwks_pci_tbl,
|
||||
.probe = svwks_init_one,
|
||||
@ -454,12 +454,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init svwks_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&svwks_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit svwks_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&svwks_pci_driver);
|
||||
}
|
||||
|
||||
module_init(svwks_ide_init);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2008 MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
@ -150,7 +151,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
|
||||
int count = 0;
|
||||
|
||||
stat = sgiioc4_read_status(hwif);
|
||||
while ((stat & 0x80) && (count++ < 100)) {
|
||||
while ((stat & ATA_BUSY) && (count++ < 100)) {
|
||||
udelay(1);
|
||||
stat = sgiioc4_read_status(hwif);
|
||||
}
|
||||
@ -310,7 +311,7 @@ static u8 sgiioc4_read_status(ide_hwif_t *hwif)
|
||||
u8 reg = (u8) readb((void __iomem *) port);
|
||||
|
||||
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
|
||||
if (reg & 0x51) { /* Not busy...check for interrupt */
|
||||
if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
|
||||
unsigned long other_ir = port - 0x110;
|
||||
unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
|
||||
|
||||
@ -338,36 +339,32 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
|
||||
if (dma_base == 0)
|
||||
return -1;
|
||||
|
||||
printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
|
||||
dma_base, dma_base + num_ports - 1);
|
||||
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
|
||||
|
||||
if (!request_mem_region(dma_base, num_ports, hwif->name)) {
|
||||
printk(KERN_ERR
|
||||
"%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
|
||||
"ALREADY in use\n",
|
||||
__func__, hwif->name, (void *) dma_base,
|
||||
(void *) dma_base + num_ports - 1);
|
||||
if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
|
||||
printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
|
||||
"already in use\n", __func__, hwif->name,
|
||||
dma_base, dma_base + num_ports - 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
virt_dma_base = ioremap(dma_base, num_ports);
|
||||
if (virt_dma_base == NULL) {
|
||||
printk(KERN_ERR
|
||||
"%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
|
||||
__func__, hwif->name, dma_base, dma_base + num_ports - 1);
|
||||
printk(KERN_ERR "%s(%s) -- ERROR: unable to map addresses "
|
||||
"0x%lx to 0x%lx\n", __func__, hwif->name,
|
||||
dma_base, dma_base + num_ports - 1);
|
||||
goto dma_remap_failure;
|
||||
}
|
||||
hwif->dma_base = (unsigned long) virt_dma_base;
|
||||
|
||||
hwif->dmatable_cpu = pci_alloc_consistent(dev,
|
||||
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
|
||||
&hwif->dmatable_dma);
|
||||
|
||||
if (!hwif->dmatable_cpu)
|
||||
goto dma_pci_alloc_failure;
|
||||
|
||||
hwif->sg_max_nents = IOC4_PRD_ENTRIES;
|
||||
|
||||
hwif->prd_max_nents = IOC4_PRD_ENTRIES;
|
||||
hwif->prd_ent_size = IOC4_PRD_BYTES;
|
||||
|
||||
if (ide_allocate_dma_engine(hwif))
|
||||
goto dma_pci_alloc_failure;
|
||||
|
||||
pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
|
||||
(dma_addr_t *)&hwif->extra_base);
|
||||
if (pad) {
|
||||
@ -375,13 +372,11 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
|
||||
hwif->dmatable_cpu, hwif->dmatable_dma);
|
||||
printk(KERN_INFO
|
||||
"%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
|
||||
ide_release_dma_engine(hwif);
|
||||
|
||||
printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
|
||||
__func__, hwif->name);
|
||||
printk(KERN_INFO
|
||||
"Changing from DMA to PIO mode for Drive %s\n", hwif->name);
|
||||
printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
|
||||
|
||||
dma_pci_alloc_failure:
|
||||
iounmap(virt_dma_base);
|
||||
@ -617,14 +612,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
|
||||
irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
|
||||
|
||||
cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
|
||||
if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
|
||||
DRV_NAME)) {
|
||||
printk(KERN_ERR
|
||||
"%s %s: -- ERROR, Addresses "
|
||||
"0x%p to 0x%p ALREADY in use\n",
|
||||
DRV_NAME, pci_name(dev), (void *)cmd_phys_base,
|
||||
(void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
|
||||
return -ENOMEM;
|
||||
if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
|
||||
DRV_NAME) == NULL) {
|
||||
printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
|
||||
"already in use\n", DRV_NAME, pci_name(dev),
|
||||
cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Initialize the IO registers */
|
||||
|
@ -116,13 +116,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long base = (unsigned long)hwif->hwif_data;
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
base += 0xA0 + r;
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO)
|
||||
base += hwif->channel << 6;
|
||||
else
|
||||
base += hwif->channel << 4;
|
||||
base |= drive->select.b.unit << drive->select.b.unit;
|
||||
base |= unit << unit;
|
||||
return base;
|
||||
}
|
||||
|
||||
@ -255,7 +256,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
|
||||
u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
|
||||
: (mmio ? 0xB4 : 0x80);
|
||||
u8 mode = 0;
|
||||
u8 unit = drive->select.b.unit;
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
/* trim *taskfile* PIO to the slowest of the master/slave */
|
||||
if (pair) {
|
||||
@ -301,9 +302,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u16 ultra = 0, multi = 0;
|
||||
u8 mode = 0, unit = drive->select.b.unit;
|
||||
unsigned long base = (unsigned long)hwif->hwif_data;
|
||||
u16 ultra = 0, multi = 0;
|
||||
u8 mode = 0, unit = drive->dn & 1;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 scsc = 0, addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
|
||||
: (mmio ? 0xB4 : 0x80);
|
||||
@ -712,7 +713,7 @@ static const struct ide_dma_ops sil_dma_ops = {
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = ide_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = siimage_dma_test_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
@ -829,7 +830,7 @@ static const struct pci_device_id siimage_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver siimage_pci_driver = {
|
||||
.name = "SiI_IDE",
|
||||
.id_table = siimage_pci_tbl,
|
||||
.probe = siimage_init_one,
|
||||
@ -840,12 +841,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init siimage_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&siimage_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit siimage_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&siimage_pci_driver);
|
||||
}
|
||||
|
||||
module_init(siimage_ide_init);
|
||||
|
@ -605,7 +605,7 @@ static const struct pci_device_id sis5513_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver sis5513_pci_driver = {
|
||||
.name = "SIS_IDE",
|
||||
.id_table = sis5513_pci_tbl,
|
||||
.probe = sis5513_init_one,
|
||||
@ -616,12 +616,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init sis5513_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&sis5513_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit sis5513_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&sis5513_pci_driver);
|
||||
}
|
||||
|
||||
module_init(sis5513_ide_init);
|
||||
|
@ -207,7 +207,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
|
||||
|
||||
DBG(("%s(drive:%s)\n", __func__, drive->name));
|
||||
|
||||
ret = __ide_dma_end(drive);
|
||||
ret = ide_dma_end(drive);
|
||||
|
||||
pci_write_config_word(dev, reg, drive->drive_data);
|
||||
|
||||
@ -345,7 +345,7 @@ static const struct pci_device_id sl82c105_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver sl82c105_pci_driver = {
|
||||
.name = "W82C105_IDE",
|
||||
.id_table = sl82c105_pci_tbl,
|
||||
.probe = sl82c105_init_one,
|
||||
@ -356,12 +356,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init sl82c105_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&sl82c105_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit sl82c105_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&sl82c105_pci_driver);
|
||||
}
|
||||
|
||||
module_init(sl82c105_ide_init);
|
||||
|
@ -154,7 +154,7 @@ static const struct pci_device_id slc90e66_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver slc90e66_pci_driver = {
|
||||
.name = "SLC90e66_IDE",
|
||||
.id_table = slc90e66_pci_tbl,
|
||||
.probe = slc90e66_init_one,
|
||||
@ -165,12 +165,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init slc90e66_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&slc90e66_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit slc90e66_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&slc90e66_pci_driver);
|
||||
}
|
||||
|
||||
module_init(slc90e66_ide_init);
|
||||
|
@ -186,7 +186,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
|
||||
.dma_setup = ide_dma_setup,
|
||||
.dma_exec_cmd = ide_dma_exec_cmd,
|
||||
.dma_start = tc86c001_dma_start,
|
||||
.dma_end = __ide_dma_end,
|
||||
.dma_end = ide_dma_end,
|
||||
.dma_test_irq = ide_dma_test_irq,
|
||||
.dma_lost_irq = ide_dma_lost_irq,
|
||||
.dma_timeout = ide_dma_timeout,
|
||||
@ -245,7 +245,7 @@ static const struct pci_device_id tc86c001_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver tc86c001_pci_driver = {
|
||||
.name = "TC86C001",
|
||||
.id_table = tc86c001_pci_tbl,
|
||||
.probe = tc86c001_init_one,
|
||||
@ -254,12 +254,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init tc86c001_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&tc86c001_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit tc86c001_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&tc86c001_pci_driver);
|
||||
}
|
||||
|
||||
module_init(tc86c001_ide_init);
|
||||
|
@ -38,13 +38,12 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u8 channel_offset = hwif->channel ? 0x74 : 0x70;
|
||||
u16 timing = 0;
|
||||
u32 triflex_timings = 0;
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
|
||||
u16 timing = 0;
|
||||
u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
|
||||
|
||||
pci_read_config_dword(dev, channel_offset, &triflex_timings);
|
||||
|
||||
|
||||
switch(speed) {
|
||||
case XFER_MW_DMA_2:
|
||||
timing = 0x0103;
|
||||
@ -114,7 +113,7 @@ static const struct pci_device_id triflex_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver triflex_pci_driver = {
|
||||
.name = "TRIFLEX_IDE",
|
||||
.id_table = triflex_pci_tbl,
|
||||
.probe = triflex_init_one,
|
||||
@ -125,12 +124,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init triflex_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&triflex_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit triflex_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&triflex_pci_driver);
|
||||
}
|
||||
|
||||
module_init(triflex_ide_init);
|
||||
|
@ -161,7 +161,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
|
||||
}
|
||||
|
||||
/* enable IRQ if not probing */
|
||||
if (drive->present) {
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
reg = inw(hwif->config_data + 3);
|
||||
reg &= 0x13;
|
||||
reg &= ~(1 << hwif->channel);
|
||||
@ -173,7 +173,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
|
||||
|
||||
static void trm290_selectproc (ide_drive_t *drive)
|
||||
{
|
||||
trm290_prepare_drive(drive, drive->using_dma);
|
||||
trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
|
||||
}
|
||||
|
||||
static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
|
||||
@ -350,7 +350,7 @@ static const struct pci_device_id trm290_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver trm290_pci_driver = {
|
||||
.name = "TRM290_IDE",
|
||||
.id_table = trm290_pci_tbl,
|
||||
.probe = trm290_init_one,
|
||||
@ -359,12 +359,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init trm290_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&trm290_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit trm290_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&trm290_pci_driver);
|
||||
}
|
||||
|
||||
module_init(trm290_ide_init);
|
||||
|
@ -487,7 +487,7 @@ static const struct pci_device_id via_pci_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, via_pci_tbl);
|
||||
|
||||
static struct pci_driver driver = {
|
||||
static struct pci_driver via_pci_driver = {
|
||||
.name = "VIA_IDE",
|
||||
.id_table = via_pci_tbl,
|
||||
.probe = via_init_one,
|
||||
@ -498,12 +498,12 @@ static struct pci_driver driver = {
|
||||
|
||||
static int __init via_ide_init(void)
|
||||
{
|
||||
return ide_pci_register_driver(&driver);
|
||||
return ide_pci_register_driver(&via_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit via_ide_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&driver);
|
||||
pci_unregister_driver(&via_pci_driver);
|
||||
}
|
||||
|
||||
module_init(via_ide_init);
|
||||
|
@ -430,10 +430,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
|
||||
if (pmif == NULL)
|
||||
return;
|
||||
|
||||
if (drive->select.b.unit & 0x01)
|
||||
if (drive->dn & 1)
|
||||
writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
|
||||
else
|
||||
writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
|
||||
@ -452,10 +449,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
|
||||
if (pmif == NULL)
|
||||
return;
|
||||
|
||||
if (drive->select.b.unit & 0x01) {
|
||||
if (drive->dn & 1) {
|
||||
writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
|
||||
writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
|
||||
} else {
|
||||
@ -475,9 +469,6 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
|
||||
if (pmif == NULL)
|
||||
return;
|
||||
|
||||
if (pmif->kind == controller_sh_ata6 ||
|
||||
pmif->kind == controller_un_ata6 ||
|
||||
pmif->kind == controller_k2_ata6)
|
||||
@ -524,11 +515,8 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
unsigned accessTime, recTime;
|
||||
unsigned int cycle_time;
|
||||
|
||||
if (pmif == NULL)
|
||||
return;
|
||||
|
||||
/* which drive is it ? */
|
||||
timings = &pmif->timings[drive->select.b.unit & 0x01];
|
||||
timings = &pmif->timings[drive->dn & 1];
|
||||
t = *timings;
|
||||
|
||||
cycle_time = ide_pio_cycle_time(drive, pio);
|
||||
@ -805,9 +793,9 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
int unit = (drive->select.b.unit & 0x01);
|
||||
int ret = 0;
|
||||
u32 *timings, *timings2, tl[2];
|
||||
u8 unit = drive->dn & 1;
|
||||
|
||||
timings = &pmif->timings[unit];
|
||||
timings2 = &pmif->timings[unit+2];
|
||||
@ -966,11 +954,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
|
||||
if (pmif->mediabay) {
|
||||
#ifdef CONFIG_PMAC_MEDIABAY
|
||||
if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
|
||||
drive->noprobe = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
drive->noprobe = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_NOPROBE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1535,18 +1523,6 @@ use_pio_instead:
|
||||
return 0; /* revert to PIO for this request */
|
||||
}
|
||||
|
||||
/* Teardown mappings after DMA has completed. */
|
||||
static void
|
||||
pmac_ide_destroy_dmatable (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if (hwif->sg_nents) {
|
||||
ide_destroy_dmatable(drive);
|
||||
hwif->sg_nents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare a DMA transfer. We build the DMA table, adjust the timings for
|
||||
* a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
|
||||
@ -1558,12 +1534,7 @@ pmac_ide_dma_setup(ide_drive_t *drive)
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 ata4;
|
||||
|
||||
if (pmif == NULL)
|
||||
return 1;
|
||||
ata4 = (pmif->kind == controller_kl_ata4);
|
||||
u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
|
||||
|
||||
if (!pmac_ide_build_dmatable(drive, rq)) {
|
||||
ide_map_sg(drive, rq);
|
||||
@ -1617,17 +1588,15 @@ pmac_ide_dma_end (ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
volatile struct dbdma_regs __iomem *dma;
|
||||
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
|
||||
u32 dstat;
|
||||
|
||||
if (pmif == NULL)
|
||||
return 0;
|
||||
dma = pmif->dma_regs;
|
||||
|
||||
drive->waiting_for_dma = 0;
|
||||
dstat = readl(&dma->status);
|
||||
writel(((RUN|WAKE|DEAD) << 16), &dma->control);
|
||||
pmac_ide_destroy_dmatable(drive);
|
||||
|
||||
ide_destroy_dmatable(drive);
|
||||
|
||||
/* verify good dma status. we don't check for ACTIVE beeing 0. We should...
|
||||
* in theory, but with ATAPI decices doing buffer underruns, that would
|
||||
* cause us to disable DMA, which isn't what we want
|
||||
@ -1647,13 +1616,9 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
volatile struct dbdma_regs __iomem *dma;
|
||||
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
|
||||
unsigned long status, timeout;
|
||||
|
||||
if (pmif == NULL)
|
||||
return 0;
|
||||
dma = pmif->dma_regs;
|
||||
|
||||
/* We have to things to deal with here:
|
||||
*
|
||||
* - The dbdma won't stop if the command was started
|
||||
@ -1672,9 +1637,6 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
|
||||
status = readl(&dma->status);
|
||||
if (!(status & ACTIVE))
|
||||
return 1;
|
||||
if (!drive->waiting_for_dma)
|
||||
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
|
||||
called while not waiting\n", HWIF(drive)->index);
|
||||
|
||||
/* If dbdma didn't execute the STOP command yet, the
|
||||
* active bit is still set. We consider that we aren't
|
||||
@ -1709,14 +1671,9 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
pmac_ide_hwif_t *pmif =
|
||||
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
|
||||
volatile struct dbdma_regs __iomem *dma;
|
||||
unsigned long status;
|
||||
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
|
||||
unsigned long status = readl(&dma->status);
|
||||
|
||||
if (pmif == NULL)
|
||||
return;
|
||||
dma = pmif->dma_regs;
|
||||
|
||||
status = readl(&dma->status);
|
||||
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,6 @@ typedef struct ide_scsi_obj {
|
||||
struct gendisk *disk;
|
||||
struct Scsi_Host *host;
|
||||
|
||||
struct ide_atapi_pc *pc; /* Current packet command */
|
||||
unsigned long transform; /* SCSI cmd translation layer */
|
||||
unsigned long log; /* log flags */
|
||||
} idescsi_scsi_t;
|
||||
@ -137,10 +136,10 @@ static void ide_scsi_hex_dump(u8 *data, int len)
|
||||
|
||||
static int idescsi_end_request(ide_drive_t *, int, int);
|
||||
|
||||
static void ide_scsi_callback(ide_drive_t *drive)
|
||||
static void ide_scsi_callback(ide_drive_t *drive, int dsc)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
struct ide_atapi_pc *pc = scsi->pc;
|
||||
struct ide_atapi_pc *pc = drive->pc;
|
||||
|
||||
if (pc->flags & PC_FLAG_TIMEDOUT)
|
||||
debug_log("%s: got timed out packet %lu at %lu\n", __func__,
|
||||
@ -267,49 +266,10 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
|
||||
spin_unlock_irqrestore(host->host_lock, flags);
|
||||
kfree(pc);
|
||||
blk_put_request(rq);
|
||||
scsi->pc = NULL;
|
||||
drive->pc = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned long get_timeout(struct ide_atapi_pc *pc)
|
||||
{
|
||||
return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
|
||||
}
|
||||
|
||||
static int idescsi_expiry(ide_drive_t *drive)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
struct ide_atapi_pc *pc = scsi->pc;
|
||||
|
||||
debug_log("%s called for %lu at %lu\n", __func__,
|
||||
pc->scsi_cmd->serial_number, jiffies);
|
||||
|
||||
pc->flags |= PC_FLAG_TIMEDOUT;
|
||||
|
||||
return 0; /* we do not want the ide subsystem to retry */
|
||||
}
|
||||
|
||||
/*
|
||||
* Our interrupt handler.
|
||||
*/
|
||||
static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
struct ide_atapi_pc *pc = scsi->pc;
|
||||
|
||||
return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc),
|
||||
idescsi_expiry, NULL, NULL, NULL,
|
||||
ide_io_buffers);
|
||||
}
|
||||
|
||||
static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
|
||||
return ide_transfer_pc(drive, scsi->pc, idescsi_pc_intr,
|
||||
get_timeout(scsi->pc), idescsi_expiry);
|
||||
}
|
||||
|
||||
static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
|
||||
{
|
||||
switch (pc->c[0]) {
|
||||
@ -352,13 +312,10 @@ static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
|
||||
static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
|
||||
struct ide_atapi_pc *pc)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
|
||||
/* Set the current packet command */
|
||||
scsi->pc = pc;
|
||||
drive->pc = pc;
|
||||
|
||||
return ide_issue_pc(drive, pc, idescsi_transfer_pc,
|
||||
get_timeout(pc), idescsi_expiry);
|
||||
return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -374,7 +331,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
|
||||
if (blk_sense_request(rq) || blk_special_request(rq)) {
|
||||
struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
|
||||
|
||||
if (drive->using_dma && !idescsi_map_sg(drive, pc))
|
||||
if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&
|
||||
idescsi_map_sg(drive, pc) == 0)
|
||||
pc->flags |= PC_FLAG_DMA_OK;
|
||||
|
||||
return idescsi_issue_pc(drive, pc);
|
||||
@ -427,14 +385,14 @@ static const struct ide_proc_devset idescsi_settings[] = {
|
||||
*/
|
||||
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
|
||||
{
|
||||
if ((drive->id[ATA_ID_CONFIG] & 0x0060) == 0x20)
|
||||
set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
|
||||
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
|
||||
#if IDESCSI_DEBUG_LOG
|
||||
set_bit(IDESCSI_LOG_CMD, &scsi->log);
|
||||
#endif /* IDESCSI_DEBUG_LOG */
|
||||
|
||||
drive->pc_callback = ide_scsi_callback;
|
||||
drive->pc_callback = ide_scsi_callback;
|
||||
drive->pc_update_buffers = NULL;
|
||||
drive->pc_io_buffers = ide_io_buffers;
|
||||
|
||||
ide_proc_register_driver(drive, scsi->driver);
|
||||
}
|
||||
@ -456,7 +414,7 @@ static void ide_scsi_remove(ide_drive_t *drive)
|
||||
|
||||
ide_scsi_put(scsi);
|
||||
|
||||
drive->scsi = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_SCSI;
|
||||
}
|
||||
|
||||
static int ide_scsi_probe(ide_drive_t *);
|
||||
@ -477,7 +435,6 @@ static ide_driver_t idescsi_driver = {
|
||||
.probe = ide_scsi_probe,
|
||||
.remove = ide_scsi_remove,
|
||||
.version = IDESCSI_VERSION,
|
||||
.media = ide_scsi,
|
||||
.do_request = idescsi_do_request,
|
||||
.end_request = idescsi_end_request,
|
||||
.error = idescsi_atapi_error,
|
||||
@ -622,6 +579,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
|
||||
int busy;
|
||||
int ret = FAILED;
|
||||
|
||||
struct ide_atapi_pc *pc;
|
||||
|
||||
/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
|
||||
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
@ -642,26 +601,27 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
|
||||
spin_lock_irq(&ide_lock);
|
||||
|
||||
/* If there is no pc running we're done (our interrupt took care of it) */
|
||||
if (!scsi->pc) {
|
||||
pc = drive->pc;
|
||||
if (pc == NULL) {
|
||||
ret = SUCCESS;
|
||||
goto ide_unlock;
|
||||
}
|
||||
|
||||
/* It's somewhere in flight. Does ide subsystem agree? */
|
||||
if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
|
||||
elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
|
||||
if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
|
||||
elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {
|
||||
/*
|
||||
* FIXME - not sure this condition can ever occur
|
||||
*/
|
||||
printk (KERN_ERR "ide-scsi: cmd aborted!\n");
|
||||
|
||||
if (blk_sense_request(scsi->pc->rq))
|
||||
kfree(scsi->pc->buf);
|
||||
if (blk_sense_request(pc->rq))
|
||||
kfree(pc->buf);
|
||||
/* we need to call blk_put_request twice. */
|
||||
blk_put_request(scsi->pc->rq);
|
||||
blk_put_request(scsi->pc->rq);
|
||||
kfree(scsi->pc);
|
||||
scsi->pc = NULL;
|
||||
blk_put_request(pc->rq);
|
||||
blk_put_request(pc->rq);
|
||||
kfree(pc);
|
||||
drive->pc = NULL;
|
||||
|
||||
ret = SUCCESS;
|
||||
}
|
||||
@ -683,6 +643,8 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
int ready = 0;
|
||||
int ret = SUCCESS;
|
||||
|
||||
struct ide_atapi_pc *pc;
|
||||
|
||||
/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
|
||||
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
@ -697,7 +659,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
spin_lock_irq(cmd->device->host->host_lock);
|
||||
spin_lock(&ide_lock);
|
||||
|
||||
if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
|
||||
pc = drive->pc;
|
||||
|
||||
if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
|
||||
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
|
||||
spin_unlock(&ide_lock);
|
||||
spin_unlock_irq(cmd->device->host->host_lock);
|
||||
@ -708,9 +672,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
if (__blk_end_request(req, -EIO, 0))
|
||||
BUG();
|
||||
if (blk_sense_request(req))
|
||||
kfree(scsi->pc->buf);
|
||||
kfree(scsi->pc);
|
||||
scsi->pc = NULL;
|
||||
kfree(pc->buf);
|
||||
kfree(pc);
|
||||
drive->pc = NULL;
|
||||
blk_put_request(req);
|
||||
|
||||
/* now nuke the drive queue */
|
||||
@ -801,7 +765,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
|
||||
!(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
|
||||
return -ENODEV;
|
||||
|
||||
drive->scsi = 1;
|
||||
drive->dev_flags |= IDE_DFLAG_SCSI;
|
||||
|
||||
g = alloc_disk(1 << PARTN_BITS);
|
||||
if (!g)
|
||||
@ -842,7 +806,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
|
||||
|
||||
put_disk(g);
|
||||
out_host_put:
|
||||
drive->scsi = 0;
|
||||
drive->dev_flags &= ~IDE_DFLAG_SCSI;
|
||||
scsi_host_put(host);
|
||||
return err;
|
||||
}
|
||||
|
1585
include/linux/ide.h
1585
include/linux/ide.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user