提交 5c3c4d9b 编写于 作者: L Linus Torvalds

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: (71 commits)
  ide: Remove ide_spin_wait_hwgroup() and use special requests instead
  ide: move IDE{FLOPPY,TAPE}_WAIT_CMD defines to <linux/ide.h>
  ide: add ide_do_test_unit_ready() helper
  ide: add ide_do_start_stop() helper
  ide: add ide_set_media_lock() helper
  ide-floppy: move floppy ioctls handling to ide-floppy_ioctl.c
  ide-floppy: ->{srfp,wp} -> IDE_AFLAG_{SRFP,WP}
  ide: add ide_queue_pc_tail() helper
  ide: add ide_queue_pc_head() helper
  ide: add ide_init_pc() helper
  ide-tape: add ide_tape_set_media_lock() helper
  ide-floppy: add ide_floppy_set_media_lock() helper
  ide: add ide_io_buffers() helper
  ide-scsi: cleanup ide_scsi_io_buffers()
  ide-floppy: remove MODE_SENSE_* defines
  ide-{floppy,tape}: remove packet command stack
  ide-{floppy,tape}: remove request stack
  ide-generic: handle probing of legacy io-ports v5
  ide-floppy: use scatterlists for pio transfers
  ide-tape: remove idetape_init_rq()
  ...
...@@ -503,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -503,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[0] = ATA_16; scsi_cmd[0] = ATA_16;
scsi_cmd[4] = args[2]; scsi_cmd[4] = args[2];
if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */ if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too */
scsi_cmd[6] = args[3]; scsi_cmd[6] = args[3];
scsi_cmd[8] = args[1]; scsi_cmd[8] = args[1];
scsi_cmd[10] = 0x4f; scsi_cmd[10] = 0x4f;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/ata.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#define REALLY_SLOW_IO #define REALLY_SLOW_IO
...@@ -370,7 +371,7 @@ static void reset_hd(void) ...@@ -370,7 +371,7 @@ static void reset_hd(void)
struct hd_i_struct *disk = &hd_info[i]; struct hd_i_struct *disk = &hd_info[i];
disk->special_op = disk->recalibrate = 1; disk->special_op = disk->recalibrate = 1;
hd_out(disk, disk->sect, disk->sect, disk->head-1, hd_out(disk, disk->sect, disk->sect, disk->head-1,
disk->cyl, WIN_SPECIFY, &reset_hd); disk->cyl, ATA_CMD_INIT_DEV_PARAMS, &reset_hd);
if (reset) if (reset)
goto repeat; goto repeat;
} else } else
...@@ -558,7 +559,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) ...@@ -558,7 +559,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
{ {
if (disk->recalibrate) { if (disk->recalibrate) {
disk->recalibrate = 0; disk->recalibrate = 0;
hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr); hd_out(disk, disk->sect, 0, 0, 0, ATA_CMD_RESTORE, &recal_intr);
return reset; return reset;
} }
if (disk->head > 16) { if (disk->head > 16) {
...@@ -631,13 +632,13 @@ static void hd_request(void) ...@@ -631,13 +632,13 @@ static void hd_request(void)
if (blk_fs_request(req)) { if (blk_fs_request(req)) {
switch (rq_data_dir(req)) { switch (rq_data_dir(req)) {
case READ: case READ:
hd_out(disk, nsect, sec, head, cyl, WIN_READ, hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ,
&read_intr); &read_intr);
if (reset) if (reset)
goto repeat; goto repeat;
break; break;
case WRITE: case WRITE:
hd_out(disk, nsect, sec, head, cyl, WIN_WRITE, hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_WRITE,
&write_intr); &write_intr);
if (reset) if (reset)
goto repeat; goto repeat;
......
...@@ -131,29 +131,6 @@ config BLK_DEV_IDEDISK ...@@ -131,29 +131,6 @@ config BLK_DEV_IDEDISK
If unsure, say Y. If unsure, say Y.
config IDEDISK_MULTI_MODE
bool "Use multiple sector mode for Programmed Input/Output by default"
help
This setting is irrelevant for most IDE disks, with direct memory
access, to which multiple sector mode does not apply. Multiple sector
mode is a feature of most modern IDE hard drives, permitting the
transfer of multiple sectors per Programmed Input/Output interrupt,
rather than the usual one sector per interrupt. When this feature is
enabled, it can reduce operating system overhead for disk Programmed
Input/Output. On some systems, it also can increase the data
throughput of Programmed Input/Output. Some drives, however, seemed
to run slower with multiple sector mode enabled. Some drives claimed
to support multiple sector mode, but lost data at some settings.
Under rare circumstances, such failures could result in massive
filesystem corruption.
If you get the following error, try to say Y here:
hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
hda: set_multmode: error=0x04 { DriveStatusError }
If in doubt, say N.
config BLK_DEV_IDECS config BLK_DEV_IDECS
tristate "PCMCIA IDE support" tristate "PCMCIA IDE support"
depends on PCMCIA depends on PCMCIA
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
EXTRA_CFLAGS += -Idrivers/ide EXTRA_CFLAGS += -Idrivers/ide
ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o \ ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
ide-pio-blacklist.o ide-taskfile.o ide-pio-blacklist.o
# core IDE code # core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
...@@ -37,11 +37,12 @@ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o ...@@ -37,11 +37,12 @@ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.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 obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_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 obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
ifeq ($(CONFIG_BLK_DEV_IDECS), y) ifeq ($(CONFIG_BLK_DEV_IDECS), y)
ide-cs-core-y += legacy/ide-cs.o ide-cs-core-y += legacy/ide-cs.o
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -265,8 +264,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) ...@@ -265,8 +264,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
* If we're going to be doing MW_DMA_1 or MW_DMA_2, we should * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
* take care to note the values in the ID... * take care to note the values in the ID...
*/ */
if (use_dma_info && drive->id->eide_dma_time > cycle_time) if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
cycle_time = drive->id->eide_dma_time; cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
drive->drive_data = cycle_time; drive->drive_data = cycle_time;
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -180,7 +179,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, ...@@ -180,7 +179,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
val32 |= (t2i << (dev ? 8 : 0)); val32 |= (t2i << (dev ? 8 : 0));
writel(val32, base + BK3710_DATRCVR); writel(val32, base + BK3710_DATRCVR);
if (mate && mate->present) { if (mate) {
u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
if (mode2 < mode) if (mode2 < mode)
...@@ -213,7 +212,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) ...@@ -213,7 +212,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
palm_bk3710_setudmamode(base, is_slave, palm_bk3710_setudmamode(base, is_slave,
xferspeed - XFER_UDMA_0); xferspeed - XFER_UDMA_0);
} else { } else {
palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min, palm_bk3710_setdmamode(base, is_slave,
drive->id[ATA_ID_EIDE_DMA_MIN],
xferspeed); xferspeed);
} }
} }
...@@ -229,7 +229,7 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio) ...@@ -229,7 +229,7 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
* Obtain the drive PIO data for tuning the Palm Chip registers * Obtain the drive PIO data for tuning the Palm Chip registers
*/ */
cycle_time = ide_pio_cycle_time(drive, pio); cycle_time = ide_pio_cycle_time(drive, pio);
mate = ide_get_paired_drive(drive); mate = ide_get_pair_dev(drive);
palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
} }
......
...@@ -584,7 +584,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) ...@@ -584,7 +584,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
* This function executes the _STM ACPI method for the target channel. * This function executes the _STM ACPI method for the target channel.
* *
* _STM requires Identify Drive data, which has to passed as an argument. * _STM requires Identify Drive data, which has to passed as an argument.
* Unfortunately hd_driveid is a mangled version which we can't readily * Unfortunately drive->id is a mangled version which we can't readily
* use; hence we'll get the information afresh. * use; hence we'll get the information afresh.
*/ */
void ide_acpi_push_timing(ide_hwif_t *hwif) void ide_acpi_push_timing(ide_hwif_t *hwif)
...@@ -614,10 +614,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) ...@@ -614,10 +614,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
in_params[0].buffer.length = sizeof(struct GTM_buffer); in_params[0].buffer.length = sizeof(struct GTM_buffer);
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
in_params[1].type = ACPI_TYPE_BUFFER; in_params[1].type = ACPI_TYPE_BUFFER;
in_params[1].buffer.length = sizeof(struct hd_driveid); in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[1].buffer.pointer = (u8 *)&master->idbuff; in_params[1].buffer.pointer = (u8 *)&master->idbuff;
in_params[2].type = ACPI_TYPE_BUFFER; in_params[2].type = ACPI_TYPE_BUFFER;
in_params[2].buffer.length = sizeof(struct hd_driveid); in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[2].buffer.pointer = (u8 *)&slave->idbuff; in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
/* Output buffer: _STM has no output */ /* Output buffer: _STM has no output */
......
...@@ -14,12 +14,201 @@ ...@@ -14,12 +14,201 @@
#define debug_log(fmt, args...) do {} while (0) #define debug_log(fmt, args...) do {} while (0)
#endif #endif
/*
* Check whether we can support a device,
* based on the ATAPI IDENTIFY command results.
*/
int ide_check_atapi_device(ide_drive_t *drive, const char *s)
{
u16 *id = drive->id;
u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
*((u16 *)&gcw) = id[ATA_ID_CONFIG];
protocol = (gcw[1] & 0xC0) >> 6;
device_type = gcw[1] & 0x1F;
removable = (gcw[0] & 0x80) >> 7;
drq_type = (gcw[0] & 0x60) >> 5;
packet_size = gcw[0] & 0x03;
#ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */
if (drive->media == ide_floppy && device_type == 5 &&
!strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
strstr((char *)&id[ATA_ID_PROD], "ZIP"))
device_type = 0;
#endif
if (protocol != 2)
printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n",
s, drive->name, protocol);
else if ((drive->media == ide_floppy && device_type != 0) ||
(drive->media == ide_tape && device_type != 1))
printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n",
s, drive->name, device_type);
else if (removable == 0)
printk(KERN_ERR "%s: %s: the removable flag is not set\n",
s, drive->name);
else if (drive->media == ide_floppy && drq_type == 3)
printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
"supported\n", s, drive->name, drq_type);
else if (packet_size != 0)
printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
"bytes\n", s, drive->name, packet_size);
else
return 1;
return 0;
}
EXPORT_SYMBOL_GPL(ide_check_atapi_device);
/* PIO data transfer routine using the scatter gather table. */
int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
struct scatterlist *sg = pc->sg;
char *buf;
int count, done = 0;
while (bcount) {
count = min(sg->length - pc->b_count, bcount);
if (PageHighMem(sg_page(sg))) {
unsigned long flags;
local_irq_save(flags);
buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
xf(drive, NULL, buf + pc->b_count, count);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
local_irq_restore(flags);
} else {
buf = sg_virt(sg);
xf(drive, NULL, buf + pc->b_count, count);
}
bcount -= count;
pc->b_count += count;
done += count;
if (pc->b_count == sg->length) {
if (!--pc->sg_cnt)
break;
pc->sg = sg = sg_next(sg);
pc->b_count = 0;
}
}
if (bcount) {
printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
bcount, write ? "padding with zeros"
: "discarding data");
ide_pad_transfer(drive, write, bcount);
}
return done;
}
EXPORT_SYMBOL_GPL(ide_io_buffers);
void ide_init_pc(struct ide_atapi_pc *pc)
{
memset(pc, 0, sizeof(*pc));
pc->buf = pc->pc_buf;
pc->buf_size = IDE_PC_BUFFER_SIZE;
}
EXPORT_SYMBOL_GPL(ide_init_pc);
/*
* Generate a new packet command request in front of the request queue, before
* 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)
{
blk_rq_init(NULL, rq);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_PREEMPT;
rq->buffer = (char *)pc;
rq->rq_disk = disk;
memcpy(rq->cmd, pc->c, 12);
if (drive->media == ide_tape)
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,
* and wait for it to be serviced.
*/
int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
struct ide_atapi_pc *pc)
{
struct request *rq;
int error;
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->buffer = (char *)pc;
memcpy(rq->cmd, pc->c, 12);
if (drive->media == ide_tape)
rq->cmd[13] = REQ_IDETAPE_PC1;
error = blk_execute_rq(drive->queue, disk, rq, 0);
blk_put_request(rq);
return error;
}
EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
{
struct ide_atapi_pc pc;
ide_init_pc(&pc);
pc.c[0] = TEST_UNIT_READY;
return ide_queue_pc_tail(drive, disk, &pc);
}
EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
{
struct ide_atapi_pc pc;
ide_init_pc(&pc);
pc.c[0] = START_STOP;
pc.c[4] = start;
if (drive->media == ide_tape)
pc.flags |= PC_FLAG_WAIT_FOR_DSC;
return ide_queue_pc_tail(drive, disk, &pc);
}
EXPORT_SYMBOL_GPL(ide_do_start_stop);
int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
{
struct ide_atapi_pc pc;
if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
return 0;
ide_init_pc(&pc);
pc.c[0] = ALLOW_MEDIUM_REMOVAL;
pc.c[4] = on;
return ide_queue_pc_tail(drive, disk, &pc);
}
EXPORT_SYMBOL_GPL(ide_set_media_lock);
/* TODO: unify the code thus making some arguments go away */ /* 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_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, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq; struct request *rq = hwif->hwgroup->rq;
...@@ -41,7 +230,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -41,7 +230,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) || if (hwif->dma_ops->dma_end(drive) ||
(drive->media == ide_tape && !scsi && (stat & ERR_STAT))) { (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
if (drive->media == ide_floppy && !scsi) if (drive->media == ide_floppy && !scsi)
printk(KERN_ERR "%s: DMA %s error\n", printk(KERN_ERR "%s: DMA %s error\n",
drive->name, rq_data_dir(pc->rq) drive->name, rq_data_dir(pc->rq)
...@@ -56,7 +245,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -56,7 +245,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
} }
/* No more interrupts */ /* No more interrupts */
if ((stat & DRQ_STAT) == 0) { if ((stat & ATA_DRQ) == 0) {
debug_log("Packet command completed, %d bytes transferred\n", debug_log("Packet command completed, %d bytes transferred\n",
pc->xferred); pc->xferred);
...@@ -65,10 +254,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -65,10 +254,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_enable_in_hardirq(); local_irq_enable_in_hardirq();
if (drive->media == ide_tape && !scsi && if (drive->media == ide_tape && !scsi &&
(stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE) (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
stat &= ~ERR_STAT; stat &= ~ATA_ERR;
if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
/* Error detected */ /* Error detected */
debug_log("%s: I/O error\n", drive->name); debug_log("%s: I/O error\n", drive->name);
...@@ -95,7 +284,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -95,7 +284,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
cmd_finished: cmd_finished:
pc->error = 0; pc->error = 0;
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
(stat & SEEK_STAT) == 0) { (stat & ATA_DSC) == 0) {
dsc_handle(drive); dsc_handle(drive);
return ide_stopped; return ide_stopped;
} }
...@@ -117,17 +306,18 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -117,17 +306,18 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
/* Get the number of bytes to transfer on this interrupt. */ /* Get the number of bytes to transfer on this interrupt. */
ide_read_bcount_and_ireason(drive, &bcount, &ireason); ide_read_bcount_and_ireason(drive, &bcount, &ireason);
if (ireason & CD) { if (ireason & ATAPI_COD) {
printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
return ide_do_reset(drive); return ide_do_reset(drive);
} }
if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { if (((ireason & ATAPI_IO) == ATAPI_IO) ==
!!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */ /* Hopefully, we will never get here */
printk(KERN_ERR "%s: We wanted to %s, but the device wants us " printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
"to %s!\n", drive->name, "to %s!\n", drive->name,
(ireason & IO) ? "Write" : "Read", (ireason & ATAPI_IO) ? "Write" : "Read",
(ireason & IO) ? "Read" : "Write"); (ireason & ATAPI_IO) ? "Read" : "Write");
return ide_do_reset(drive); return ide_do_reset(drive);
} }
...@@ -171,9 +361,14 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -171,9 +361,14 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
if ((drive->media == ide_floppy && !scsi && !pc->buf) || if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
(drive->media == ide_tape && !scsi && pc->bh) || (drive->media == ide_tape && !scsi && pc->bh) ||
(scsi && pc->sg)) (scsi && pc->sg)) {
io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); int done = io_buffers(drive, pc, bcount,
else !!(pc->flags & PC_FLAG_WRITING));
/* FIXME: don't do partial completions */
if (drive->media == ide_floppy && !scsi)
ide_end_request(drive, 1, done >> 9);
} else
xferfunc(drive, NULL, pc->cur_pos, bcount); xferfunc(drive, NULL, pc->cur_pos, bcount);
/* Update the current position */ /* Update the current position */
...@@ -205,7 +400,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) ...@@ -205,7 +400,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
{ {
int retries = 100; int retries = 100;
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { while (retries-- && ((ireason & ATAPI_COD) == 0 ||
(ireason & ATAPI_IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name); "a packet command, retrying\n", drive->name);
udelay(100); udelay(100);
...@@ -214,8 +410,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) ...@@ -214,8 +410,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n", "a packet command, ignoring\n",
drive->name); drive->name);
ireason |= CD; ireason |= ATAPI_COD;
ireason &= ~IO; ireason &= ~ATAPI_IO;
} }
} }
...@@ -231,7 +427,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -231,7 +427,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
ide_startstop_t startstop; ide_startstop_t startstop;
u8 ireason; u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet " printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name); "DRQ isn't asserted\n", drive->name);
return startstop; return startstop;
...@@ -241,7 +437,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -241,7 +437,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (drive->media == ide_tape && !drive->scsi) if (drive->media == ide_tape && !drive->scsi)
ireason = ide_wait_ireason(drive, ireason); ireason = ide_wait_ireason(drive, ireason);
if ((ireason & CD) == 0 || (ireason & IO)) { if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
"a packet command\n", drive->name); "a packet command\n", drive->name);
return ide_do_reset(drive); return ide_do_reset(drive);
...@@ -303,7 +499,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -303,7 +499,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
/* Issue the packet command */ /* Issue the packet command */
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
ide_execute_command(drive, WIN_PACKETCMD, handler, ide_execute_command(drive, ATA_CMD_PACKET, handler,
timeout, NULL); timeout, NULL);
return ide_started; return ide_started;
} else { } else {
......
...@@ -436,7 +436,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) ...@@ -436,7 +436,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
ide_dump_status_no_sense(drive, "media error (blank)", ide_dump_status_no_sense(drive, "media error (blank)",
stat); stat);
do_end_request = 1; do_end_request = 1;
} else if ((err & ~ABRT_ERR) != 0) { } else if ((err & ~ATA_ABORTED) != 0) {
/* go to the default handler for other errors */ /* go to the default handler for other errors */
ide_error(drive, "cdrom_decode_status", stat); ide_error(drive, "cdrom_decode_status", stat);
return 1; return 1;
...@@ -457,7 +457,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) ...@@ -457,7 +457,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
* If we got a CHECK_CONDITION status, queue * If we got a CHECK_CONDITION status, queue
* a request sense command. * a request sense command.
*/ */
if (stat & ERR_STAT) if (stat & ATA_ERR)
cdrom_queue_request_sense(drive, NULL, NULL); cdrom_queue_request_sense(drive, NULL, NULL);
} else { } else {
blk_dump_rq_flags(rq, "ide-cd: bad rq"); blk_dump_rq_flags(rq, "ide-cd: bad rq");
...@@ -468,7 +468,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) ...@@ -468,7 +468,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
return 1; return 1;
end_request: end_request:
if (stat & ERR_STAT) { if (stat & ATA_ERR) {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
...@@ -541,7 +541,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, ...@@ -541,7 +541,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
/* packet command */ /* packet command */
ide_execute_command(drive, WIN_PACKETCMD, handler, ide_execute_command(drive, ATA_CMD_PACKET, handler,
ATAPI_WAIT_PC, cdrom_timer_expiry); ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started; return ide_started;
} else { } else {
...@@ -574,7 +574,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, ...@@ -574,7 +574,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
*/ */
/* check for errors */ /* check for errors */
if (cdrom_decode_status(drive, DRQ_STAT, NULL)) if (cdrom_decode_status(drive, ATA_DRQ, NULL))
return ide_stopped; return ide_stopped;
/* ok, next interrupt will be DMA interrupt */ /* ok, next interrupt will be DMA interrupt */
...@@ -582,8 +582,8 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, ...@@ -582,8 +582,8 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
} else { } else {
/* otherwise, we must wait for DRQ to get set */ /* otherwise, we must wait for DRQ to get set */
if (ide_wait_stat(&startstop, drive, DRQ_STAT, if (ide_wait_stat(&startstop, drive, ATA_DRQ,
BUSY_STAT, WAIT_READY)) ATA_BUSY, WAIT_READY))
return startstop; return startstop;
} }
...@@ -938,7 +938,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ...@@ -938,7 +938,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
thislen = len; thislen = len;
/* If DRQ is clear, the command has completed. */ /* If DRQ is clear, the command has completed. */
if ((stat & DRQ_STAT) == 0) { if ((stat & ATA_DRQ) == 0) {
if (blk_fs_request(rq)) { if (blk_fs_request(rq)) {
/* /*
* If we're not done reading/writing, complain. * If we're not done reading/writing, complain.
...@@ -1164,13 +1164,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) ...@@ -1164,13 +1164,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
struct request_queue *q = drive->queue; struct request_queue *q = drive->queue;
unsigned int alignment; unsigned int alignment;
unsigned long addr; char *buf;
unsigned long stack_mask = ~(THREAD_SIZE - 1);
if (rq->bio) if (rq->bio)
addr = (unsigned long)bio_data(rq->bio); buf = bio_data(rq->bio);
else else
addr = (unsigned long)rq->data; buf = rq->data;
info->dma = drive->using_dma; info->dma = drive->using_dma;
...@@ -1181,11 +1180,8 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) ...@@ -1181,11 +1180,8 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
* separate masks. * separate masks.
*/ */
alignment = queue_dma_alignment(q) | q->dma_pad_mask; alignment = queue_dma_alignment(q) | q->dma_pad_mask;
if (addr & alignment || rq->data_len & alignment) if ((unsigned long)buf & alignment || rq->data_len & alignment
info->dma = 0; || object_is_on_stack(buf))
if (!((addr & stack_mask) ^
((unsigned long)current->stack & stack_mask)))
info->dma = 0; info->dma = 0;
} }
} }
...@@ -1206,7 +1202,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, ...@@ -1206,7 +1202,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
unsigned long elapsed = jiffies - info->start_seek; unsigned long elapsed = jiffies - info->start_seek;
int stat = hwif->tp_ops->read_status(hwif); int stat = hwif->tp_ops->read_status(hwif);
if ((stat & SEEK_STAT) != SEEK_STAT) { if ((stat & ATA_DSC) != ATA_DSC) {
if (elapsed < IDECD_SEEK_TIMEOUT) { if (elapsed < IDECD_SEEK_TIMEOUT) {
ide_stall_queue(drive, ide_stall_queue(drive,
IDECD_SEEK_TIMER); IDECD_SEEK_TIMER);
...@@ -1813,13 +1809,12 @@ static ide_proc_entry_t idecd_proc[] = { ...@@ -1813,13 +1809,12 @@ static ide_proc_entry_t idecd_proc[] = {
{ NULL, 0, NULL, NULL } { NULL, 0, NULL, NULL }
}; };
static void ide_cdrom_add_settings(ide_drive_t *drive) ide_devset_rw_field(dsc_overlap, dsc_overlap);
{
ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, static const struct ide_proc_devset idecd_settings[] = {
&drive->dsc_overlap, NULL); IDE_PROC_DEVSET(dsc_overlap, 0, 1),
} { 0 },
#else };
static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
#endif #endif
static const struct cd_list_entry ide_cd_quirks_list[] = { static const struct cd_list_entry ide_cd_quirks_list[] = {
...@@ -1866,14 +1861,14 @@ static const struct cd_list_entry ide_cd_quirks_list[] = { ...@@ -1866,14 +1861,14 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
static unsigned int ide_cd_flags(struct hd_driveid *id) static unsigned int ide_cd_flags(u16 *id)
{ {
const struct cd_list_entry *cle = ide_cd_quirks_list; const struct cd_list_entry *cle = ide_cd_quirks_list;
while (cle->id_model) { while (cle->id_model) {
if (strcmp(cle->id_model, id->model) == 0 && if (strcmp(cle->id_model, (char *)&id[ATA_ID_PROD]) == 0 &&
(cle->id_firmware == NULL || (cle->id_firmware == NULL ||
strstr(id->fw_rev, cle->id_firmware))) strstr((char *)&id[ATA_ID_FW_REV], cle->id_firmware)))
return cle->cd_flags; return cle->cd_flags;
cle++; cle++;
} }
...@@ -1885,7 +1880,8 @@ static int ide_cdrom_setup(ide_drive_t *drive) ...@@ -1885,7 +1880,8 @@ static int ide_cdrom_setup(ide_drive_t *drive)
{ {
struct cdrom_info *cd = drive->driver_data; struct cdrom_info *cd = drive->driver_data;
struct cdrom_device_info *cdi = &cd->devinfo; struct cdrom_device_info *cdi = &cd->devinfo;
struct hd_driveid *id = drive->id; u16 *id = drive->id;
char *fw_rev = (char *)&id[ATA_ID_FW_REV];
int nslots; int nslots;
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
...@@ -1900,15 +1896,15 @@ static int ide_cdrom_setup(ide_drive_t *drive) ...@@ -1900,15 +1896,15 @@ static int ide_cdrom_setup(ide_drive_t *drive)
drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT | drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id); ide_cd_flags(id);
if ((id->config & 0x0060) == 0x20) if ((id[ATA_ID_CONFIG] & 0x0060) == 0x20)
drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) && if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') fw_rev[4] == '1' && fw_rev[6] <= '2')
drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD | drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
IDE_AFLAG_TOCADDR_AS_BCD); IDE_AFLAG_TOCADDR_AS_BCD);
else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) && else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') fw_rev[4] == '1' && fw_rev[6] <= '2')
drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD; drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD) else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */ /* 3 => use CD in slot 0 */
...@@ -1927,7 +1923,8 @@ static int ide_cdrom_setup(ide_drive_t *drive) ...@@ -1927,7 +1923,8 @@ static int ide_cdrom_setup(ide_drive_t *drive)
cd->devinfo.handle = NULL; cd->devinfo.handle = NULL;
return 1; return 1;
} }
ide_cdrom_add_settings(drive);
ide_proc_register_driver(drive, cd->driver);
return 0; return 0;
} }
...@@ -1972,12 +1969,12 @@ static ide_driver_t ide_cdrom_driver = { ...@@ -1972,12 +1969,12 @@ static ide_driver_t ide_cdrom_driver = {
.remove = ide_cd_remove, .remove = ide_cd_remove,
.version = IDECD_VERSION, .version = IDECD_VERSION,
.media = ide_cdrom, .media = ide_cdrom,
.supports_dsc_overlap = 1,
.do_request = ide_cd_do_request, .do_request = ide_cd_do_request,
.end_request = ide_end_request, .end_request = ide_end_request,
.error = __ide_error, .error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS #ifdef CONFIG_IDE_PROC_FS
.proc = idecd_proc, .proc = idecd_proc,
.settings = idecd_settings,
#endif #endif
}; };
...@@ -2112,10 +2109,10 @@ static int ide_cd_probe(ide_drive_t *drive) ...@@ -2112,10 +2109,10 @@ static int ide_cd_probe(ide_drive_t *drive)
if (!strstr("ide-cdrom", drive->driver_req)) if (!strstr("ide-cdrom", drive->driver_req))
goto failed; goto failed;
if (!drive->present)
goto failed;
if (drive->media != ide_cdrom && drive->media != ide_optical) if (drive->media != ide_cdrom && drive->media != ide_optical)
goto failed; goto failed;
/* skip drives that we were told to ignore */ /* skip drives that we were told to ignore */
if (ignore != NULL) { if (ignore != NULL) {
if (strstr(ignore, drive->name)) { if (strstr(ignore, drive->name)) {
...@@ -2137,8 +2134,6 @@ static int ide_cd_probe(ide_drive_t *drive) ...@@ -2137,8 +2134,6 @@ static int ide_cd_probe(ide_drive_t *drive)
ide_init_disk(g, drive); ide_init_disk(g, drive);
ide_proc_register_driver(drive, &ide_cdrom_driver);
kref_init(&info->kref); kref_init(&info->kref);
info->drive = drive; info->drive = drive;
...@@ -2153,7 +2148,6 @@ static int ide_cd_probe(ide_drive_t *drive) ...@@ -2153,7 +2148,6 @@ static int ide_cd_probe(ide_drive_t *drive)
g->driverfs_dev = &drive->gendev; g->driverfs_dev = &drive->gendev;
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) { if (ide_cdrom_setup(drive)) {
ide_proc_unregister_driver(drive, &ide_cdrom_driver);
ide_cd_release(&info->kref); ide_cd_release(&info->kref);
goto failed; goto failed;
} }
......
此差异已折叠。
...@@ -106,7 +106,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive) ...@@ -106,7 +106,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
dma_stat = hwif->dma_ops->dma_end(drive); dma_stat = hwif->dma_ops->dma_end(drive);
stat = hwif->tp_ops->read_status(hwif); stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
if (!dma_stat) { if (!dma_stat) {
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
...@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable); ...@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
static int config_drive_for_dma (ide_drive_t *drive) static int config_drive_for_dma (ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id; u16 *id = drive->id;
if (drive->media != ide_disk) { if (drive->media != ide_disk) {
if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA) if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
...@@ -299,16 +299,17 @@ static int config_drive_for_dma (ide_drive_t *drive) ...@@ -299,16 +299,17 @@ static int config_drive_for_dma (ide_drive_t *drive)
* Enable DMA on any drive that has * Enable DMA on any drive that has
* UltraDMA (mode 0/1/2/3/4/5/6) enabled * UltraDMA (mode 0/1/2/3/4/5/6) enabled
*/ */
if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) if ((id[ATA_ID_FIELD_VALID] & 4) &&
((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
return 1; return 1;
/* /*
* Enable DMA on any drive that has mode2 DMA * Enable DMA on any drive that has mode2 DMA
* (multi or single) enabled * (multi or single) enabled
*/ */
if (id->field_valid & 2) /* regular DMA */ if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
if ((id->dma_mword & 0x404) == 0x404 || if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
(id->dma_1word & 0x404) == 0x404) (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
return 1; return 1;
/* Consult the list of known "good" drives */ /* Consult the list of known "good" drives */
...@@ -591,12 +592,12 @@ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; } ...@@ -591,12 +592,12 @@ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
int __ide_dma_bad_drive (ide_drive_t *drive) int __ide_dma_bad_drive (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
int blacklist = ide_in_drive_list(id, drive_blacklist); int blacklist = ide_in_drive_list(id, drive_blacklist);
if (blacklist) { if (blacklist) {
printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n", printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n",
drive->name, id->model); drive->name, (char *)&id[ATA_ID_PROD]);
return blacklist; return blacklist;
} }
return 0; return 0;
...@@ -612,21 +613,21 @@ static const u8 xfer_mode_bases[] = { ...@@ -612,21 +613,21 @@ static const u8 xfer_mode_bases[] = {
static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops; const struct ide_port_ops *port_ops = hwif->port_ops;
unsigned int mask = 0; unsigned int mask = 0;
switch(base) { switch(base) {
case XFER_UDMA_0: case XFER_UDMA_0:
if ((id->field_valid & 4) == 0) if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
break; break;
if (port_ops && port_ops->udma_filter) if (port_ops && port_ops->udma_filter)
mask = port_ops->udma_filter(drive); mask = port_ops->udma_filter(drive);
else else
mask = hwif->ultra_mask; mask = hwif->ultra_mask;
mask &= id->dma_ultra; mask &= id[ATA_ID_UDMA_MODES];
/* /*
* avoid false cable warning from eighty_ninty_three() * avoid false cable warning from eighty_ninty_three()
...@@ -637,19 +638,19 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) ...@@ -637,19 +638,19 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
} }
break; break;
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
if ((id->field_valid & 2) == 0) if ((id[ATA_ID_FIELD_VALID] & 2) == 0)
break; break;
if (port_ops && port_ops->mdma_filter) if (port_ops && port_ops->mdma_filter)
mask = port_ops->mdma_filter(drive); mask = port_ops->mdma_filter(drive);
else else
mask = hwif->mwdma_mask; mask = hwif->mwdma_mask;
mask &= id->dma_mword; mask &= id[ATA_ID_MWDMA_MODES];
break; break;
case XFER_SW_DMA_0: case XFER_SW_DMA_0:
if (id->field_valid & 2) { if (id[ATA_ID_FIELD_VALID] & 2) {
mask = id->dma_1word & hwif->swdma_mask; mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask;
} else if (id->tDMA) { } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) {
u8 mode = id->tDMA; u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8;
/* /*
* if the mode is valid convert it to the mask * if the mode is valid convert it to the mask
...@@ -706,7 +707,8 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) ...@@ -706,7 +707,8 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
/* /*
* is this correct? * is this correct?
*/ */
if (ide_dma_good_drive(drive) && drive->id->eide_dma_time < 150) if (ide_dma_good_drive(drive) &&
drive->id[ATA_ID_EIDE_DMA_TIME] < 150)
mode = XFER_MW_DMA_1; mode = XFER_MW_DMA_1;
} }
...@@ -725,7 +727,7 @@ static int ide_tune_dma(ide_drive_t *drive) ...@@ -725,7 +727,7 @@ static int ide_tune_dma(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
u8 speed; u8 speed;
if (drive->nodma || (drive->id->capability & 1) == 0) if (drive->nodma || ata_id_has_dma(drive->id) == 0)
return 0; return 0;
/* consult the list of known "bad" drives */ /* consult the list of known "bad" drives */
...@@ -767,13 +769,15 @@ static int ide_dma_check(ide_drive_t *drive) ...@@ -767,13 +769,15 @@ static int ide_dma_check(ide_drive_t *drive)
int ide_id_dma_bug(ide_drive_t *drive) int ide_id_dma_bug(ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
if (id->field_valid & 4) { if (id[ATA_ID_FIELD_VALID] & 4) {
if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) if ((id[ATA_ID_UDMA_MODES] >> 8) &&
(id[ATA_ID_MWDMA_MODES] >> 8))
goto err_out; goto err_out;
} else if (id->field_valid & 2) { } else if (id[ATA_ID_FIELD_VALID] & 2) {
if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
(id[ATA_ID_SWDMA_MODES] >> 8))
goto err_out; goto err_out;
} }
return 0; return 0;
......
此差异已折叠。
#ifndef __IDE_FLOPPY_H
#define __IDE_FLOPPY_H
/*
* Most of our global data which we need to save even as we leave the driver
* due to an interrupt or a timer event is stored in a variable of type
* idefloppy_floppy_t, defined below.
*/
typedef struct ide_floppy_obj {
ide_drive_t *drive;
ide_driver_t *driver;
struct gendisk *disk;
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 */
/* Current format */
int blocks, block_size, bs_factor;
/* Last format capacity descriptor */
u8 cap_desc[8];
/* Copy of the flexible disk page */
u8 flexible_disk_page[32];
} idefloppy_floppy_t;
/*
* Pages of the SELECT SENSE / MODE SENSE packet commands.
* See SFF-8070i spec.
*/
#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
/* IOCTLs used in low-level formatting. */
#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
/* 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 *);
/* ide-floppy_ioctl.c */
int ide_floppy_format_ioctl(ide_drive_t *, struct file *, unsigned int,
void __user *);
#endif /*__IDE_FLOPPY_H */
/*
* ide-floppy IOCTLs handling.
*/
#include <linux/kernel.h>
#include <linux/ide.h>
#include <linux/cdrom.h>
#include <asm/unaligned.h>
#include <scsi/scsi_ioctl.h>
#include "ide-floppy.h"
/*
* Obtain the list of formattable capacities.
* Very similar to ide_floppy_get_capacity, except that we push the capacity
* descriptors to userland, instead of our own structures.
*
* Userland gives us the following structure:
*
* struct idefloppy_format_capacities {
* int nformats;
* struct {
* int nblocks;
* int blocksize;
* } formats[];
* };
*
* userland initializes nformats to the number of allocated formats[] records.
* On exit we set nformats to the number of records we've actually initialized.
*/
static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
{
struct ide_floppy_obj *floppy = drive->driver_data;
struct ide_atapi_pc pc;
u8 header_len, desc_cnt;
int i, blocks, length, u_array_size, u_index;
int __user *argp;
if (get_user(u_array_size, arg))
return -EFAULT;
if (u_array_size <= 0)
return -EINVAL;
ide_floppy_create_read_capacity_cmd(&pc);
if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
return -EIO;
}
header_len = pc.buf[3];
desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
u_index = 0;
argp = arg + 1;
/*
* We always skip the first capacity descriptor. That's the current
* capacity. We are interested in the remaining descriptors, the
* formattable capacities.
*/
for (i = 1; i < desc_cnt; i++) {
unsigned int desc_start = 4 + i*8;
if (u_index >= u_array_size)
break; /* User-supplied buffer too small */
blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
if (put_user(blocks, argp))
return -EFAULT;
++argp;
if (put_user(length, argp))
return -EFAULT;
++argp;
++u_index;
}
if (put_user(u_index, arg))
return -EFAULT;
return 0;
}
static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
int l, int flags)
{
ide_init_pc(pc);
pc->c[0] = GPCMD_FORMAT_UNIT;
pc->c[1] = 0x17;
memset(pc->buf, 0, 12);
pc->buf[1] = 0xA2;
/* Default format list header, u8 1: FOV/DCRT/IMM bits set */
if (flags & 1) /* Verify bit on... */
pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
pc->buf[3] = 8;
put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
pc->buf_size = 12;
pc->flags |= PC_FLAG_WRITING;
}
static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
struct ide_atapi_pc pc;
drive->atapi_flags &= ~IDE_AFLAG_SRFP;
ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
pc.flags |= PC_FLAG_SUPPRESS_ERROR;
if (ide_queue_pc_tail(drive, floppy->disk, &pc))
return 1;
if (pc.buf[8 + 2] & 0x40)
drive->atapi_flags |= IDE_AFLAG_SRFP;
return 0;
}
static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
{
idefloppy_floppy_t *floppy = drive->driver_data;
struct ide_atapi_pc pc;
int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
/* Don't format if someone is using the disk */
drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return -EBUSY;
}
drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
/*
* Send ATAPI_FORMAT_UNIT to the drive.
*
* Userland gives us the following structure:
*
* struct idefloppy_format_command {
* int nblocks;
* int blocksize;
* int flags;
* } ;
*
* flags is a bitmask, currently, the only defined flag is:
*
* 0x01 - verify media after format.
*/
if (get_user(blocks, arg) ||
get_user(length, arg+1) ||
get_user(flags, arg+2)) {
err = -EFAULT;
goto out;
}
(void)ide_floppy_get_sfrp_bit(drive);
ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);
if (ide_queue_pc_tail(drive, floppy->disk, &pc))
err = -EIO;
out:
if (err)
drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return err;
}
/*
* Get ATAPI_FORMAT_UNIT progress indication.
*
* Userland gives a pointer to an int. The int is set to a progress
* indicator 0-65536, with 65536=100%.
*
* If the drive does not support format progress indication, we just check
* the dsc bit, and return either 0 or 65536.
*/
static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
{
idefloppy_floppy_t *floppy = drive->driver_data;
struct ide_atapi_pc pc;
int progress_indication = 0x10000;
if (drive->atapi_flags & IDE_AFLAG_SRFP) {
ide_floppy_create_request_sense_cmd(&pc);
if (ide_queue_pc_tail(drive, floppy->disk, &pc))
return -EIO;
if (floppy->sense_key == 2 &&
floppy->asc == 4 &&
floppy->ascq == 4)
progress_indication = floppy->progress_indication;
/* Else assume format_unit has finished, and we're at 0x10000 */
} else {
ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
u8 stat;
local_irq_save(flags);
stat = hwif->tp_ops->read_status(hwif);
local_irq_restore(flags);
progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000;
}
if (put_user(progress_indication, arg))
return -EFAULT;
return 0;
}
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:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
return ide_floppy_get_format_capacities(drive, argp);
case IDEFLOPPY_IOCTL_FORMAT_START:
if (!(file->f_mode & 2))
return -EPERM;
return ide_floppy_format_unit(drive, (int __user *)argp);
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
return ide_floppy_get_format_progress(drive, argp);
default:
return -ENOTTY;
}
}
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/pci_ids.h>
/* FIXME: convert m32r to use ide_platform host driver */ /* FIXME: convert m32r to use ide_platform host driver */
#ifdef CONFIG_M32R #ifdef CONFIG_M32R
...@@ -27,7 +28,7 @@ ...@@ -27,7 +28,7 @@
#define DRV_NAME "ide_generic" #define DRV_NAME "ide_generic"
static int probe_mask = 0x03; static int probe_mask;
module_param(probe_mask, int, 0); module_param(probe_mask, int, 0);
MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
...@@ -100,19 +101,65 @@ static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; ...@@ -100,19 +101,65 @@ static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 }; static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 };
#endif #endif
static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary)
{
struct pci_dev *p = NULL;
u16 val;
for_each_pci_dev(p) {
if (pci_resource_start(p, 0) == 0x1f0)
*primary = 1;
if (pci_resource_start(p, 2) == 0x170)
*secondary = 1;
/* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */
if (p->vendor == PCI_VENDOR_ID_CYRIX &&
(p->device == PCI_DEVICE_ID_CYRIX_5510 ||
p->device == PCI_DEVICE_ID_CYRIX_5520))
*primary = *secondary = 1;
/* Intel MPIIX - PIO ATA on non PCI side of bridge */
if (p->vendor == PCI_VENDOR_ID_INTEL &&
p->device == PCI_DEVICE_ID_INTEL_82371MX) {
pci_read_config_word(p, 0x6C, &val);
if (val & 0x8000) {
/* ATA port enabled */
if (val & 0x4000)
*secondary = 1;
else
*primary = 1;
}
}
}
}
static int __init ide_generic_init(void) static int __init ide_generic_init(void)
{ {
hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS]; hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
struct ide_host *host; struct ide_host *host;
unsigned long io_addr; unsigned long io_addr;
int i, rc; int i, rc, primary = 0, secondary = 0;
#ifdef CONFIG_MIPS #ifdef CONFIG_MIPS
if (!ide_probe_legacy()) if (!ide_probe_legacy())
return -ENODEV; return -ENODEV;
#endif #endif
printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module " ide_generic_check_pci_legacy_iobases(&primary, &secondary);
"parameter for probing all legacy ISA IDE ports\n");
if (!probe_mask) {
printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" "
"module parameter for probing all legacy ISA IDE ports\n");
if (primary == 0)
probe_mask |= 0x1;
if (secondary == 0)
probe_mask |= 0x2;
} else
printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports "
"upon user request\n");
memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS); memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
...@@ -183,18 +184,18 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * ...@@ -183,18 +184,18 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
if (drive->media != ide_disk) if (drive->media != ide_disk)
break; break;
/* Not supported? Switch to next step now. */ /* Not supported? Switch to next step now. */
if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0) {
ide_complete_power_step(drive, rq, 0, 0); ide_complete_power_step(drive, rq, 0, 0);
return ide_stopped; return ide_stopped;
} }
if (ide_id_has_flush_cache_ext(drive->id)) if (ata_id_flush_ext_enabled(drive->id))
args->tf.command = WIN_FLUSH_CACHE_EXT; args->tf.command = ATA_CMD_FLUSH_EXT;
else else
args->tf.command = WIN_FLUSH_CACHE; args->tf.command = ATA_CMD_FLUSH;
goto out_do_tf; goto out_do_tf;
case idedisk_pm_standby: /* Suspend step 2 (standby) */ case idedisk_pm_standby: /* Suspend step 2 (standby) */
args->tf.command = WIN_STANDBYNOW1; args->tf.command = ATA_CMD_STANDBYNOW1;
goto out_do_tf; goto out_do_tf;
case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
...@@ -209,7 +210,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * ...@@ -209,7 +210,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped; return ide_stopped;
case idedisk_pm_idle: /* Resume step 2 (idle) */ case idedisk_pm_idle: /* Resume step 2 (idle) */
args->tf.command = WIN_IDLEIMMEDIATE; args->tf.command = ATA_CMD_IDLEIMMEDIATE;
goto out_do_tf; goto out_do_tf;
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
...@@ -322,7 +323,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) ...@@ -322,7 +323,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
ide_task_t *task = (ide_task_t *)rq->special; ide_task_t *task = (ide_task_t *)rq->special;
if (rq->errors == 0) if (rq->errors == 0)
rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT); rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
if (task) { if (task) {
struct ide_taskfile *tf = &task->tf; struct ide_taskfile *tf = &task->tf;
...@@ -373,29 +374,29 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 ...@@ -373,29 +374,29 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
/* other bits are useless when BUSY */ /* other bits are useless when BUSY */
rq->errors |= ERROR_RESET; rq->errors |= ERROR_RESET;
} else if (stat & ERR_STAT) { } else if (stat & ATA_ERR) {
/* err has different meaning on cdrom and tape */ /* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) { if (err == ATA_ABORTED) {
if (drive->select.b.lba && if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */ /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
hwif->tp_ops->read_status(hwif) == WIN_SPECIFY) hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
return ide_stopped; return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) { } else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */ /* UDMA crc error, just retry the operation */
drive->crc_count++; drive->crc_count++;
} else if (err & (BBD_ERR | ECC_ERR)) { } else if (err & (ATA_BBK | ATA_UNC)) {
/* retries won't help these */ /* retries won't help these */
rq->errors = ERROR_MAX; rq->errors = ERROR_MAX;
} else if (err & TRK0_ERR) { } else if (err & ATA_TRK0NF) {
/* help it find track zero */ /* help it find track zero */
rq->errors |= ERROR_RECAL; rq->errors |= ERROR_RECAL;
} }
} }
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
(hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
int nsect = drive->mult_count ? drive->mult_count : 1; int nsect = drive->mult_count ? drive->mult_count : 1;
...@@ -407,7 +408,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 ...@@ -407,7 +408,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
return ide_stopped; return ide_stopped;
} }
if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
rq->errors |= ERROR_RESET; rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) { if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
...@@ -427,16 +428,16 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u ...@@ -427,16 +428,16 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
/* other bits are useless when BUSY */ /* other bits are useless when BUSY */
rq->errors |= ERROR_RESET; rq->errors |= ERROR_RESET;
} else { } else {
/* add decoding error stuff */ /* add decoding error stuff */
} }
if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
/* force an abort */ /* force an abort */
hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE); hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
if (rq->errors >= ERROR_MAX) { if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq); ide_kill_rq(drive, rq);
...@@ -509,19 +510,19 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) ...@@ -509,19 +510,19 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
tf->lbam = drive->cyl; tf->lbam = drive->cyl;
tf->lbah = drive->cyl >> 8; tf->lbah = drive->cyl >> 8;
tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA; tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
tf->command = WIN_SPECIFY; tf->command = ATA_CMD_INIT_DEV_PARAMS;
} }
static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{ {
tf->nsect = drive->sect; tf->nsect = drive->sect;
tf->command = WIN_RESTORE; tf->command = ATA_CMD_RESTORE;
} }
static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{ {
tf->nsect = drive->mult_req; tf->nsect = drive->mult_req;
tf->command = WIN_SETMULT; tf->command = ATA_CMD_SET_MULTI;
} }
static ide_startstop_t ide_disk_special(ide_drive_t *drive) static ide_startstop_t ide_disk_special(ide_drive_t *drive)
...@@ -540,8 +541,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) ...@@ -540,8 +541,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
ide_tf_set_restore_cmd(drive, &args.tf); ide_tf_set_restore_cmd(drive, &args.tf);
} else if (s->b.set_multmode) { } else if (s->b.set_multmode) {
s->b.set_multmode = 0; s->b.set_multmode = 0;
if (drive->mult_req > drive->id->max_multsect)
drive->mult_req = drive->id->max_multsect;
ide_tf_set_setmult_cmd(drive, &args.tf); ide_tf_set_setmult_cmd(drive, &args.tf);
} else if (s->all) { } else if (s->all) {
int special = s->all; int special = s->all;
...@@ -586,9 +585,10 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) ...@@ -586,9 +585,10 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
* do_special - issue some special commands * do_special - issue some special commands
* @drive: drive the command is for * @drive: drive the command is for
* *
* do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
* commands to a drive. It used to do much more, but has been scaled * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
* back. *
* It used to do much more, but has been scaled back.
*/ */
static ide_startstop_t do_special (ide_drive_t *drive) static ide_startstop_t do_special (ide_drive_t *drive)
...@@ -716,9 +716,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, ...@@ -716,9 +716,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return ide_stopped; return ide_stopped;
} }
int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
int arg)
{
struct request_queue *q = drive->queue;
struct request *rq;
int ret = 0;
if (!(setting->flags & DS_SYNC))
return setting->set(drive, arg);
rq = blk_get_request(q, READ, GFP_KERNEL);
if (!rq)
return -ENOMEM;
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 5;
rq->cmd[0] = REQ_DEVSET_EXEC;
*(int *)&rq->cmd[1] = arg;
rq->special = setting->set;
if (blk_execute_rq(q, NULL, rq, 0))
ret = rq->errors;
blk_put_request(rq);
return ret;
}
EXPORT_SYMBOL_GPL(ide_devset_execute);
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
{ {
switch (rq->cmd[0]) { switch (rq->cmd[0]) {
case REQ_DEVSET_EXEC:
{
int err, (*setfunc)(ide_drive_t *, int) = rq->special;
err = setfunc(drive, *(int *)&rq->cmd[1]);
if (err)
rq->errors = err;
else
err = 1;
ide_end_request(drive, err, 0);
return ide_stopped;
}
case REQ_DRIVE_RESET: case REQ_DRIVE_RESET:
return ide_do_reset(drive); return ide_do_reset(drive);
default: default:
...@@ -766,9 +806,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) ...@@ -766,9 +806,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* start_request - start of I/O and command issuing for IDE * start_request - start of I/O and command issuing for IDE
* *
* start_request() initiates handling of a new I/O request. It * start_request() initiates handling of a new I/O request. It
* accepts commands and I/O (read/write) requests. It also does * accepts commands and I/O (read/write) requests.
* the final remapping for weird stuff like EZDrive. Once
* device mapper can work sector level the EZDrive stuff can go away
* *
* FIXME: this function needs a rename * FIXME: this function needs a rename
*/ */
...@@ -776,7 +814,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) ...@@ -776,7 +814,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{ {
ide_startstop_t startstop; ide_startstop_t startstop;
sector_t block;
BUG_ON(!blk_rq_started(rq)); BUG_ON(!blk_rq_started(rq));
...@@ -791,21 +828,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) ...@@ -791,21 +828,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
goto kill_rq; goto kill_rq;
} }
block = rq->sector;
if (blk_fs_request(rq) &&
(drive->media == ide_disk || drive->media == ide_floppy)) {
block += drive->sect0;
}
/* Yecch - this will shift the entire interval,
possibly killing some innocent following sector */
if (block == 0 && drive->remap_0_to_1 == 1)
block = 1; /* redirect MBR access to EZ-Drive partn table */
if (blk_pm_request(rq)) if (blk_pm_request(rq))
ide_check_pm_state(drive, rq); ide_check_pm_state(drive, rq);
SELECT_DRIVE(drive); SELECT_DRIVE(drive);
if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { if (ide_wait_stat(&startstop, drive, drive->ready_stat,
ATA_BUSY | ATA_DRQ, WAIT_READY)) {
printk(KERN_ERR "%s: drive not ready for command\n", drive->name); printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
return startstop; return startstop;
} }
...@@ -844,7 +872,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) ...@@ -844,7 +872,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
return ide_special_rq(drive, rq); return ide_special_rq(drive, rq);
drv = *(ide_driver_t **)rq->rq_disk->private_data; drv = *(ide_driver_t **)rq->rq_disk->private_data;
return drv->do_request(drive, rq, block);
return drv->do_request(drive, rq, rq->sector);
} }
return do_special(drive); return do_special(drive);
kill_rq: kill_rq:
...@@ -1325,7 +1354,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) ...@@ -1325,7 +1354,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
if (hwif->irq == irq) { if (hwif->irq == irq) {
stat = hwif->tp_ops->read_status(hwif); stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
/* Try to not flood the console with msgs */ /* Try to not flood the console with msgs */
static unsigned long last_msgtime, count; static unsigned long last_msgtime, count;
++count; ++count;
......
/*
* IDE ioctls handling.
*/
#include <linux/hdreg.h>
#include <linux/ide.h>
static const struct ide_ioctl_devset ide_ioctl_settings[] = {
{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit },
{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings },
{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq },
{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma },
{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode },
{ 0 }
};
int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
unsigned int cmd, unsigned long arg,
const struct ide_ioctl_devset *s)
{
const struct ide_devset *ds;
unsigned long flags;
int err = -EOPNOTSUPP;
for (; (ds = s->setting); s++) {
if (ds->get && s->get_ioctl == cmd)
goto read_val;
else if (ds->set && s->set_ioctl == cmd)
goto set_val;
}
return err;
read_val:
mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = ds->get(drive);
spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
if (bdev != bdev->bd_contains)
err = -EINVAL;
else {
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
mutex_lock(&ide_setting_mtx);
err = ide_devset_execute(drive, ds, arg);
mutex_unlock(&ide_setting_mtx);
}
}
return err;
}
EXPORT_SYMBOL_GPL(ide_setting_ioctl);
static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
unsigned long arg)
{
u16 *id = NULL;
int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
int rc = 0;
if (drive->id_read == 0) {
rc = -ENOMSG;
goto out;
}
id = kmalloc(size, GFP_KERNEL);
if (id == NULL) {
rc = -ENOMEM;
goto out;
}
memcpy(id, drive->id, size);
ata_id_to_hd_driveid(id);
if (copy_to_user((void __user *)arg, id, size))
rc = -EFAULT;
kfree(id);
out:
return rc;
}
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);
}
static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
{
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
return -EPERM;
if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
(drive->media == ide_disk || drive->media == ide_floppy ||
drive->scsi))
return -EPERM;
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
drive->nice1 = (arg >> IDE_NICE_1) & 1;
return 0;
}
static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
{
u8 *buf = NULL;
int bufsize = 0, err = 0;
u8 args[4], xfer_rate = 0;
ide_task_t tfargs;
struct ide_taskfile *tf = &tfargs.tf;
u16 *id = drive->id;
if (NULL == (void *) arg) {
struct request *rq;
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
err = blk_execute_rq(drive->queue, NULL, rq, 0);
blk_put_request(rq);
return err;
}
if (copy_from_user(args, (void __user *)arg, 4))
return -EFAULT;
memset(&tfargs, 0, sizeof(ide_task_t));
tf->feature = args[2];
if (args[0] == ATA_CMD_SMART) {
tf->nsect = args[3];
tf->lbal = args[1];
tf->lbam = 0x4f;
tf->lbah = 0xc2;
tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
} else {
tf->nsect = args[1];
tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
}
tf->command = args[0];
tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
if (args[3]) {
tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
bufsize = SECTOR_SIZE * args[3];
buf = kzalloc(bufsize, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
}
if (tf->command == ATA_CMD_SET_FEATURES &&
tf->feature == SETFEATURES_XFER &&
tf->nsect >= XFER_SW_DMA_0 &&
(id[ATA_ID_UDMA_MODES] ||
id[ATA_ID_MWDMA_MODES] ||
id[ATA_ID_SWDMA_MODES])) {
xfer_rate = args[1];
if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
"be set\n", drive->name);
goto abort;
}
}
err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
args[0] = tf->status;
args[1] = tf->error;
args[2] = tf->nsect;
if (!err && xfer_rate) {
/* active-retuning-calls future */
ide_set_xfer_rate(drive, xfer_rate);
ide_driveid_update(drive);
}
abort:
if (copy_to_user((void __user *)arg, &args, 4))
err = -EFAULT;
if (buf) {
if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
err = -EFAULT;
kfree(buf);
}
return err;
}
static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
{
void __user *p = (void __user *)arg;
int err = 0;
u8 args[7];
ide_task_t task;
if (copy_from_user(args, p, 7))
return -EFAULT;
memset(&task, 0, sizeof(task));
memcpy(&task.tf_array[7], &args[1], 6);
task.tf.command = args[0];
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
err = ide_no_data_taskfile(drive, &task);
args[0] = task.tf.command;
memcpy(&args[1], &task.tf_array[7], 6);
if (copy_to_user(p, args, 7))
err = -EFAULT;
return err;
}
static int generic_drive_reset(ide_drive_t *drive)
{
struct request *rq;
int ret = 0;
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
rq->cmd_flags |= REQ_SOFTBARRIER;
if (blk_execute_rq(drive->queue, NULL, rq, 1))
ret = rq->errors;
blk_put_request(rq);
return ret;
}
int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
int err;
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
if (err != -EOPNOTSUPP)
return err;
switch (cmd) {
case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
if (bdev != bdev->bd_contains)
return -EINVAL;
return ide_get_identity_ioctl(drive, cmd, arg);
case HDIO_GET_NICE:
return ide_get_nice_ioctl(drive, arg);
case HDIO_SET_NICE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return ide_set_nice_ioctl(drive, arg);
#ifdef CONFIG_IDE_TASK_IOCTL
case HDIO_DRIVE_TASKFILE:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
if (drive->media == ide_disk)
return ide_taskfile_ioctl(drive, cmd, arg);
return -ENOMSG;
#endif
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
return ide_cmd_ioctl(drive, cmd, arg);
case HDIO_DRIVE_TASK:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
return ide_task_ioctl(drive, cmd, arg);
case HDIO_DRIVE_RESET:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return generic_drive_reset(drive);
case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (put_user(BUSSTATE_ON, (long __user *)arg))
return -EFAULT;
return 0;
case HDIO_SET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return -EOPNOTSUPP;
default:
return -EINVAL;
}
}
EXPORT_SYMBOL(generic_ide_ioctl);
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/nmi.h> #include <linux/nmi.h>
...@@ -400,97 +399,14 @@ const struct ide_tp_ops default_tp_ops = { ...@@ -400,97 +399,14 @@ const struct ide_tp_ops default_tp_ops = {
.output_data = ide_output_data, .output_data = ide_output_data,
}; };
void ide_fix_driveid (struct hd_driveid *id) void ide_fix_driveid(u16 *id)
{ {
#ifndef __LITTLE_ENDIAN #ifndef __LITTLE_ENDIAN
# ifdef __BIG_ENDIAN # ifdef __BIG_ENDIAN
int i; int i;
u16 *stringcast;
for (i = 0; i < 256; i++)
id->config = __le16_to_cpu(id->config); id[i] = __le16_to_cpu(id[i]);
id->cyls = __le16_to_cpu(id->cyls);
id->reserved2 = __le16_to_cpu(id->reserved2);
id->heads = __le16_to_cpu(id->heads);
id->track_bytes = __le16_to_cpu(id->track_bytes);
id->sector_bytes = __le16_to_cpu(id->sector_bytes);
id->sectors = __le16_to_cpu(id->sectors);
id->vendor0 = __le16_to_cpu(id->vendor0);
id->vendor1 = __le16_to_cpu(id->vendor1);
id->vendor2 = __le16_to_cpu(id->vendor2);
stringcast = (u16 *)&id->serial_no[0];
for (i = 0; i < (20/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->buf_type = __le16_to_cpu(id->buf_type);
id->buf_size = __le16_to_cpu(id->buf_size);
id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
stringcast = (u16 *)&id->fw_rev[0];
for (i = 0; i < (8/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
stringcast = (u16 *)&id->model[0];
for (i = 0; i < (40/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->dword_io = __le16_to_cpu(id->dword_io);
id->reserved50 = __le16_to_cpu(id->reserved50);
id->field_valid = __le16_to_cpu(id->field_valid);
id->cur_cyls = __le16_to_cpu(id->cur_cyls);
id->cur_heads = __le16_to_cpu(id->cur_heads);
id->cur_sectors = __le16_to_cpu(id->cur_sectors);
id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
id->lba_capacity = __le32_to_cpu(id->lba_capacity);
id->dma_1word = __le16_to_cpu(id->dma_1word);
id->dma_mword = __le16_to_cpu(id->dma_mword);
id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
id->eide_pio = __le16_to_cpu(id->eide_pio);
id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
for (i = 0; i < 2; ++i)
id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
for (i = 0; i < 4; ++i)
id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
id->queue_depth = __le16_to_cpu(id->queue_depth);
for (i = 0; i < 4; ++i)
id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
id->major_rev_num = __le16_to_cpu(id->major_rev_num);
id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
id->command_set_1 = __le16_to_cpu(id->command_set_1);
id->command_set_2 = __le16_to_cpu(id->command_set_2);
id->cfsse = __le16_to_cpu(id->cfsse);
id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
id->csf_default = __le16_to_cpu(id->csf_default);
id->dma_ultra = __le16_to_cpu(id->dma_ultra);
id->trseuc = __le16_to_cpu(id->trseuc);
id->trsEuc = __le16_to_cpu(id->trsEuc);
id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->mprc = __le16_to_cpu(id->mprc);
id->hw_config = __le16_to_cpu(id->hw_config);
id->acoustic = __le16_to_cpu(id->acoustic);
id->msrqs = __le16_to_cpu(id->msrqs);
id->sxfert = __le16_to_cpu(id->sxfert);
id->sal = __le16_to_cpu(id->sal);
id->spg = __le32_to_cpu(id->spg);
id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
for (i = 0; i < 22; i++)
id->words104_125[i] = __le16_to_cpu(id->words104_125[i]);
id->last_lun = __le16_to_cpu(id->last_lun);
id->word127 = __le16_to_cpu(id->word127);
id->dlf = __le16_to_cpu(id->dlf);
id->csfo = __le16_to_cpu(id->csfo);
for (i = 0; i < 26; i++)
id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
id->word156 = __le16_to_cpu(id->word156);
for (i = 0; i < 3; i++)
id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
id->cfa_power = __le16_to_cpu(id->cfa_power);
for (i = 0; i < 15; i++)
id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
for (i = 0; i < 30; i++)
id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
for (i = 0; i < 49; i++)
id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
id->integrity_word = __le16_to_cpu(id->integrity_word);
# else # else
# error "Please fix <asm/byteorder.h>" # error "Please fix <asm/byteorder.h>"
# endif # endif
...@@ -501,19 +417,21 @@ void ide_fix_driveid (struct hd_driveid *id) ...@@ -501,19 +417,21 @@ void ide_fix_driveid (struct hd_driveid *id)
* ide_fixstring() cleans up and (optionally) byte-swaps a text string, * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
* removing leading/trailing blanks and compressing internal blanks. * removing leading/trailing blanks and compressing internal blanks.
* It is primarily used to tidy up the model name/number fields as * It is primarily used to tidy up the model name/number fields as
* returned by the WIN_[P]IDENTIFY commands. * returned by the ATA_CMD_ID_ATA[PI] commands.
*/ */
void ide_fixstring (u8 *s, const int bytecount, const int byteswap) void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
{ {
u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
if (byteswap) { if (byteswap) {
/* convert from big-endian to host byte order */ /* convert from big-endian to host byte order */
for (p = end ; p != s;) for (p = s ; p != end ; p += 2)
be16_to_cpus((u16 *)(p -= 2)); be16_to_cpus((u16 *) p);
} }
/* strip leading blanks */ /* strip leading blanks */
p = s;
while (s != end && *s == ' ') while (s != end && *s == ' ')
++s; ++s;
/* compress internal blanks and strip trailing blanks */ /* compress internal blanks and strip trailing blanks */
...@@ -556,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive) ...@@ -556,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive)
/* Note: this may clear a pending IRQ!! */ /* Note: this may clear a pending IRQ!! */
stat = hwif->tp_ops->read_status(hwif); stat = hwif->tp_ops->read_status(hwif);
if (stat & BUSY_STAT) if (stat & ATA_BUSY)
/* drive busy: definitely not interrupting */ /* drive busy: definitely not interrupting */
return 0; return 0;
...@@ -588,10 +506,10 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti ...@@ -588,10 +506,10 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
udelay(1); /* spec allows drive 400ns to assert "BUSY" */ udelay(1); /* spec allows drive 400ns to assert "BUSY" */
stat = tp_ops->read_status(hwif); stat = tp_ops->read_status(hwif);
if (stat & BUSY_STAT) { if (stat & ATA_BUSY) {
local_irq_set(flags); local_irq_set(flags);
timeout += jiffies; timeout += jiffies;
while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) { while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
/* /*
* One last read after the timeout in case * One last read after the timeout in case
...@@ -599,7 +517,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti ...@@ -599,7 +517,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
* progress during the timeout.. * progress during the timeout..
*/ */
stat = tp_ops->read_status(hwif); stat = tp_ops->read_status(hwif);
if (!(stat & BUSY_STAT)) if ((stat & ATA_BUSY) == 0)
break; break;
local_irq_restore(flags); local_irq_restore(flags);
...@@ -660,18 +578,18 @@ EXPORT_SYMBOL(ide_wait_stat); ...@@ -660,18 +578,18 @@ EXPORT_SYMBOL(ide_wait_stat);
/** /**
* ide_in_drive_list - look for drive in black/white list * ide_in_drive_list - look for drive in black/white list
* @id: drive identifier * @id: drive identifier
* @drive_table: list to inspect * @table: list to inspect
* *
* Look for a drive in the blacklist and the whitelist tables * Look for a drive in the blacklist and the whitelist tables
* Returns 1 if the drive is found in the table. * Returns 1 if the drive is found in the table.
*/ */
int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) int ide_in_drive_list(u16 *id, const struct drive_list_entry *table)
{ {
for ( ; drive_table->id_model; drive_table++) for ( ; table->id_model; table++)
if ((!strcmp(drive_table->id_model, id->model)) && if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) &&
(!drive_table->id_firmware || (!table->id_firmware ||
strstr(id->fw_rev, drive_table->id_firmware))) strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware)))
return 1; return 1;
return 0; return 0;
} }
...@@ -702,7 +620,7 @@ static const struct drive_list_entry ivb_list[] = { ...@@ -702,7 +620,7 @@ static const struct drive_list_entry ivb_list[] = {
u8 eighty_ninty_three (ide_drive_t *drive) u8 eighty_ninty_three (ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id; u16 *id = drive->id;
int ivb = ide_in_drive_list(id, ivb_list); int ivb = ide_in_drive_list(id, ivb_list);
if (hwif->cbl == ATA_CBL_PATA40_SHORT) if (hwif->cbl == ATA_CBL_PATA40_SHORT)
...@@ -712,7 +630,7 @@ u8 eighty_ninty_three (ide_drive_t *drive) ...@@ -712,7 +630,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
printk(KERN_DEBUG "%s: skipping word 93 validity check\n", printk(KERN_DEBUG "%s: skipping word 93 validity check\n",
drive->name); drive->name);
if (ide_dev_is_sata(id) && !ivb) if (ata_id_is_sata(id) && !ivb)
return 1; return 1;
if (hwif->cbl != ATA_CBL_PATA80 && !ivb) if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
...@@ -724,7 +642,8 @@ u8 eighty_ninty_three (ide_drive_t *drive) ...@@ -724,7 +642,8 @@ u8 eighty_ninty_three (ide_drive_t *drive)
* - force bit13 (80c cable present) check also for !ivb devices * - force bit13 (80c cable present) check also for !ivb devices
* (unless the slave device is pre-ATA3) * (unless the slave device is pre-ATA3)
*/ */
if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000))) if ((id[ATA_ID_HW_CONFIG] & 0x4000) ||
(ivb && (id[ATA_ID_HW_CONFIG] & 0x2000)))
return 1; return 1;
no_80w: no_80w:
...@@ -745,8 +664,8 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -745,8 +664,8 @@ int ide_driveid_update(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_tp_ops *tp_ops = hwif->tp_ops;
struct hd_driveid *id; u16 *id;
unsigned long timeout, flags; unsigned long flags;
u8 stat; u8 stat;
/* /*
...@@ -757,29 +676,24 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -757,29 +676,24 @@ int ide_driveid_update(ide_drive_t *drive)
SELECT_MASK(drive, 1); SELECT_MASK(drive, 1);
tp_ops->set_irq(hwif, 0); tp_ops->set_irq(hwif, 0);
msleep(50); msleep(50);
tp_ops->exec_command(hwif, WIN_IDENTIFY); tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
SELECT_MASK(drive, 0);
return 0; /* drive timed-out */
}
msleep(50); /* give drive a breather */ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
stat = tp_ops->read_altstatus(hwif); SELECT_MASK(drive, 0);
} while (stat & BUSY_STAT); return 0;
}
msleep(50); /* wait for IRQ and DRQ_STAT */ msleep(50); /* wait for IRQ and ATA_DRQ */
stat = tp_ops->read_status(hwif); stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) {
SELECT_MASK(drive, 0); SELECT_MASK(drive, 0);
printk("%s: CHECK for good STATUS\n", drive->name); printk("%s: CHECK for good STATUS\n", drive->name);
return 0; return 0;
} }
local_irq_save(flags); local_irq_save(flags);
SELECT_MASK(drive, 0); SELECT_MASK(drive, 0);
id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
if (!id) { if (!id) {
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
...@@ -789,16 +703,16 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -789,16 +703,16 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_enable(); local_irq_enable();
local_irq_restore(flags); local_irq_restore(flags);
ide_fix_driveid(id); ide_fix_driveid(id);
if (id) {
drive->id->dma_ultra = id->dma_ultra; drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
drive->id->dma_mword = id->dma_mword; drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
drive->id->dma_1word = id->dma_1word; drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
/* anything more ? */ /* anything more ? */
kfree(id);
kfree(id);
if (drive->using_dma && ide_id_dma_bug(drive))
ide_dma_off(drive); if (drive->using_dma && ide_id_dma_bug(drive))
} ide_dma_off(drive);
return 1; return 1;
} }
...@@ -807,6 +721,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -807,6 +721,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u16 *id = drive->id, i;
int error = 0; int error = 0;
u8 stat; u8 stat;
ide_task_t task; ide_task_t task;
...@@ -817,7 +732,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -817,7 +732,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
#endif #endif
/* Skip setting PIO flow-control modes on pre-EIDE drives */ /* Skip setting PIO flow-control modes on pre-EIDE drives */
if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0)
goto skip; goto skip;
/* /*
...@@ -851,13 +766,13 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -851,13 +766,13 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
tp_ops->tf_load(drive, &task); tp_ops->tf_load(drive, &task);
tp_ops->exec_command(hwif, WIN_SETFEATURES); tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
if (drive->quirk_list == 2) if (drive->quirk_list == 2)
tp_ops->set_irq(hwif, 1); tp_ops->set_irq(hwif, 1);
error = __ide_wait_stat(drive, drive->ready_stat, error = __ide_wait_stat(drive, drive->ready_stat,
BUSY_STAT|DRQ_STAT|ERR_STAT, ATA_BUSY | ATA_DRQ | ATA_ERR,
WAIT_CMD, &stat); WAIT_CMD, &stat);
SELECT_MASK(drive, 0); SELECT_MASK(drive, 0);
...@@ -869,9 +784,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -869,9 +784,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
return error; return error;
} }
drive->id->dma_ultra &= ~0xFF00; id[ATA_ID_UDMA_MODES] &= ~0xFF00;
drive->id->dma_mword &= ~0x0F00; id[ATA_ID_MWDMA_MODES] &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00; id[ATA_ID_SWDMA_MODES] &= ~0x0F00;
skip: skip:
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
...@@ -881,23 +796,17 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -881,23 +796,17 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
ide_dma_off_quietly(drive); ide_dma_off_quietly(drive);
#endif #endif
switch(speed) { if (speed >= XFER_UDMA_0) {
case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; i = 1 << (speed - XFER_UDMA_0);
case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; id[ATA_ID_UDMA_MODES] |= (i << 8 | i);
case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; } else if (speed >= XFER_MW_DMA_0) {
case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; i = 1 << (speed - XFER_MW_DMA_0);
case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; } else if (speed >= XFER_SW_DMA_0) {
case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; i = 1 << (speed - XFER_SW_DMA_0);
case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; id[ATA_ID_SWDMA_MODES] |= (i << 8 | i);
case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
default: break;
} }
if (!drive->init_speed) if (!drive->init_speed)
drive->init_speed = speed; drive->init_speed = speed;
drive->current_speed = speed; drive->current_speed = speed;
...@@ -977,7 +886,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) ...@@ -977,7 +886,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD); hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
ndelay(400); ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
...@@ -1010,7 +919,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) ...@@ -1010,7 +919,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
udelay (10); udelay (10);
stat = hwif->tp_ops->read_status(hwif); stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, 0, BUSY_STAT)) if (OK_STAT(stat, 0, ATA_BUSY))
printk("%s: ATAPI reset complete\n", drive->name); printk("%s: ATAPI reset complete\n", drive->name);
else { else {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, hwgroup->poll_timeout)) {
...@@ -1056,7 +965,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) ...@@ -1056,7 +965,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
tmp = hwif->tp_ops->read_status(hwif); tmp = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(tmp, 0, BUSY_STAT)) { if (!OK_STAT(tmp, 0, ATA_BUSY)) {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/* continue polling */ /* continue polling */
...@@ -1102,7 +1011,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) ...@@ -1102,7 +1011,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
static void ide_disk_pre_reset(ide_drive_t *drive) static void ide_disk_pre_reset(ide_drive_t *drive)
{ {
int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
drive->special.all = 0; drive->special.all = 0;
drive->special.b.set_geometry = legacy; drive->special.b.set_geometry = legacy;
...@@ -1187,7 +1096,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) ...@@ -1187,7 +1096,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(drive); pre_reset(drive);
SELECT_DRIVE(drive); SELECT_DRIVE(drive);
udelay (20); udelay (20);
tp_ops->exec_command(hwif, WIN_SRST); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
ndelay(400); ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1; hwgroup->polling = 1;
...@@ -1270,7 +1179,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) ...@@ -1270,7 +1179,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
*/ */
mdelay(1); mdelay(1);
stat = hwif->tp_ops->read_status(hwif); stat = hwif->tp_ops->read_status(hwif);
if ((stat & BUSY_STAT) == 0) if ((stat & ATA_BUSY) == 0)
return 0; return 0;
/* /*
* Assume a value of 0xff means nothing is connected to * Assume a value of 0xff means nothing is connected to
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -90,29 +89,31 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) ...@@ -90,29 +89,31 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
{ {
int pio_mode; u16 *id = drive->id;
struct hd_driveid* id = drive->id; int pio_mode = -1, overridden = 0;
int overridden = 0;
if (mode_wanted != 255) if (mode_wanted != 255)
return min_t(u8, mode_wanted, max_mode); return min_t(u8, mode_wanted, max_mode);
if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 && if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
(pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
if (pio_mode != -1) {
printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
} else { } else {
pio_mode = id->tPIO; pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
pio_mode = 2; pio_mode = 2;
overridden = 1; overridden = 1;
} }
if (id->field_valid & 2) { /* drive implements ATA2? */
if (id->capability & 8) { /* IORDY supported? */ if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
if (id->eide_pio_modes & 7) { if (ata_id_has_iordy(id)) {
if (id[ATA_ID_PIO_MODES] & 7) {
overridden = 0; overridden = 0;
if (id->eide_pio_modes & 4) if (id[ATA_ID_PIO_MODES] & 4)
pio_mode = 5; pio_mode = 5;
else if (id->eide_pio_modes & 2) else if (id[ATA_ID_PIO_MODES] & 2)
pio_mode = 4; pio_mode = 4;
else else
pio_mode = 3; pio_mode = 3;
...@@ -338,16 +339,16 @@ static void ide_dump_sector(ide_drive_t *drive) ...@@ -338,16 +339,16 @@ static void ide_dump_sector(ide_drive_t *drive)
static void ide_dump_ata_error(ide_drive_t *drive, u8 err) static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
{ {
printk("{ "); printk("{ ");
if (err & ABRT_ERR) printk("DriveStatusError "); if (err & ATA_ABORTED) printk("DriveStatusError ");
if (err & ICRC_ERR) if (err & ATA_ICRC)
printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
if (err & ECC_ERR) printk("UncorrectableError "); if (err & ATA_UNC) printk("UncorrectableError ");
if (err & ID_ERR) printk("SectorIdNotFound "); if (err & ATA_IDNF) printk("SectorIdNotFound ");
if (err & TRK0_ERR) printk("TrackZeroNotFound "); if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
if (err & MARK_ERR) printk("AddrMarkNotFound "); if (err & ATA_AMNF) printk("AddrMarkNotFound ");
printk("}"); printk("}");
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
(err & (ECC_ERR|ID_ERR|MARK_ERR))) { (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
ide_dump_sector(drive); ide_dump_sector(drive);
if (HWGROUP(drive) && HWGROUP(drive)->rq) if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu", printk(", sector=%llu",
...@@ -359,12 +360,12 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err) ...@@ -359,12 +360,12 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
{ {
printk("{ "); printk("{ ");
if (err & ILI_ERR) printk("IllegalLengthIndication "); if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
if (err & EOM_ERR) printk("EndOfMedia "); if (err & ATAPI_EOM) printk("EndOfMedia ");
if (err & ABRT_ERR) printk("AbortedCommand "); if (err & ATA_ABORTED) printk("AbortedCommand ");
if (err & MCR_ERR) printk("MediaChangeRequested "); if (err & ATA_MCR) printk("MediaChangeRequested ");
if (err & LFS_ERR) printk("LastFailedSense=0x%02x ", if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
(err & LFS_ERR) >> 4); (err & ATAPI_LFS) >> 4);
printk("}\n"); printk("}\n");
} }
...@@ -386,19 +387,19 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) ...@@ -386,19 +387,19 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
local_irq_save(flags); local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
if (stat & BUSY_STAT) if (stat & ATA_BUSY)
printk("Busy "); printk("Busy ");
else { else {
if (stat & READY_STAT) printk("DriveReady "); if (stat & ATA_DRDY) printk("DriveReady ");
if (stat & WRERR_STAT) printk("DeviceFault "); if (stat & ATA_DF) printk("DeviceFault ");
if (stat & SEEK_STAT) printk("SeekComplete "); if (stat & ATA_DSC) printk("SeekComplete ");
if (stat & DRQ_STAT) printk("DataRequest "); if (stat & ATA_DRQ) printk("DataRequest ");
if (stat & ECC_STAT) printk("CorrectedError "); if (stat & ATA_CORR) printk("CorrectedError ");
if (stat & INDEX_STAT) printk("Index "); if (stat & ATA_IDX) printk("Index ");
if (stat & ERR_STAT) printk("Error "); if (stat & ATA_ERR) printk("Error ");
} }
printk("}\n"); printk("}\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
err = ide_read_error(drive); err = ide_read_error(drive);
printk("%s: %s: error=0x%02x ", drive->name, msg, err); printk("%s: %s: error=0x%02x ", drive->name, msg, err);
if (drive->media == ide_disk) if (drive->media == ide_disk)
......
...@@ -50,59 +50,54 @@ ...@@ -50,59 +50,54 @@
static void generic_id(ide_drive_t *drive) static void generic_id(ide_drive_t *drive)
{ {
drive->id->cyls = drive->cyl; u16 *id = drive->id;
drive->id->heads = drive->head;
drive->id->sectors = drive->sect; id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl;
drive->id->cur_cyls = drive->cyl; id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head;
drive->id->cur_heads = drive->head; id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect;
drive->id->cur_sectors = drive->sect;
} }
static void ide_disk_init_chs(ide_drive_t *drive) static void ide_disk_init_chs(ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
/* Extract geometry if we did not already have one for the drive */ /* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) { if (!drive->cyl || !drive->head || !drive->sect) {
drive->cyl = drive->bios_cyl = id->cyls; drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS];
drive->head = drive->bios_head = id->heads; drive->head = drive->bios_head = id[ATA_ID_HEADS];
drive->sect = drive->bios_sect = id->sectors; drive->sect = drive->bios_sect = id[ATA_ID_SECTORS];
} }
/* Handle logical geometry translation by the drive */ /* Handle logical geometry translation by the drive */
if ((id->field_valid & 1) && id->cur_cyls && if (ata_id_current_chs_valid(id)) {
id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { drive->cyl = id[ATA_ID_CUR_CYLS];
drive->cyl = id->cur_cyls; drive->head = id[ATA_ID_CUR_HEADS];
drive->head = id->cur_heads; drive->sect = id[ATA_ID_CUR_SECTORS];
drive->sect = id->cur_sectors;
} }
/* Use physical geometry if what we have still makes no sense */ /* Use physical geometry if what we have still makes no sense */
if (drive->head > 16 && id->heads && id->heads <= 16) { if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) {
drive->cyl = id->cyls; drive->cyl = id[ATA_ID_CYLS];
drive->head = id->heads; drive->head = id[ATA_ID_HEADS];
drive->sect = id->sectors; drive->sect = id[ATA_ID_SECTORS];
} }
} }
static void ide_disk_init_mult_count(ide_drive_t *drive) static void ide_disk_init_mult_count(ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff;
drive->mult_count = 0;
if (id->max_multsect) { if (max_multsect) {
#ifdef CONFIG_IDEDISK_MULTI_MODE if ((max_multsect / 2) > 1)
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id[ATA_ID_MULTSECT] = max_multsect | 0x100;
id->multsect_valid = id->multsect ? 1 : 0; else
drive->mult_req = id->multsect_valid ? id->max_multsect : 0; id[ATA_ID_MULTSECT] &= ~0x1ff;
drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
#else /* original, pre IDE-NFG, per request of AC */ drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
drive->mult_req = 0;
if (drive->mult_req > id->max_multsect) if (drive->mult_req)
drive->mult_req = id->max_multsect;
if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
drive->special.b.set_multmode = 1; drive->special.b.set_multmode = 1;
#endif
} }
} }
...@@ -119,10 +114,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) ...@@ -119,10 +114,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
static inline void do_identify (ide_drive_t *drive, u8 cmd) static inline void do_identify (ide_drive_t *drive, u8 cmd)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
int bswap = 1; u16 *id = drive->id;
struct hd_driveid *id; char *m = (char *)&id[ATA_ID_PROD];
int bswap = 1, is_cfa;
id = drive->id;
/* read 512 bytes of id info */ /* read 512 bytes of id info */
hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
...@@ -135,27 +130,28 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -135,27 +130,28 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
ide_fix_driveid(id); ide_fix_driveid(id);
/* /*
* WIN_IDENTIFY returns little-endian info, * ATA_CMD_ID_ATA returns little-endian info,
* WIN_PIDENTIFY *usually* returns little-endian info. * ATA_CMD_ID_ATAPI *usually* returns little-endian info.
*/ */
if (cmd == WIN_PIDENTIFY) { if (cmd == ATA_CMD_ID_ATAPI) {
if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ if ((m[0] == 'N' && m[1] == 'E') || /* NEC */
|| (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */
|| (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ (m[0] == 'P' && m[1] == 'i')) /* Pioneer */
/* Vertos drives may still be weird */ /* Vertos drives may still be weird */
bswap ^= 1; bswap ^= 1;
} }
ide_fixstring(id->model, sizeof(id->model), bswap);
ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring(m, ATA_ID_PROD_LEN, bswap);
ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap);
ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap);
/* we depend on this a lot! */ /* we depend on this a lot! */
id->model[sizeof(id->model)-1] = '\0'; m[ATA_ID_PROD_LEN - 1] = '\0';
if (strstr(id->model, "E X A B Y T E N E S T")) if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc; goto err_misc;
printk(KERN_INFO "%s: %s, ", drive->name, id->model); printk(KERN_INFO "%s: %s, ", drive->name, m);
drive->present = 1; drive->present = 1;
drive->dead = 0; drive->dead = 0;
...@@ -163,16 +159,16 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -163,16 +159,16 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
/* /*
* Check for an ATAPI device * Check for an ATAPI device
*/ */
if (cmd == WIN_PIDENTIFY) { if (cmd == ATA_CMD_ID_ATAPI) {
u8 type = (id->config >> 8) & 0x1f; u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
printk(KERN_CONT "ATAPI "); printk(KERN_CONT "ATAPI ");
switch (type) { switch (type) {
case ide_floppy: case ide_floppy:
if (!strstr(id->model, "CD-ROM")) { if (!strstr(m, "CD-ROM")) {
if (!strstr(id->model, "oppy") && if (!strstr(m, "oppy") &&
!strstr(id->model, "poyp") && !strstr(m, "poyp") &&
!strstr(id->model, "ZIP")) !strstr(m, "ZIP"))
printk(KERN_CONT "cdrom or floppy?, assuming "); printk(KERN_CONT "cdrom or floppy?, assuming ");
if (drive->media != ide_cdrom) { if (drive->media != ide_cdrom) {
printk(KERN_CONT "FLOPPY"); printk(KERN_CONT "FLOPPY");
...@@ -186,8 +182,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -186,8 +182,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->removable = 1; drive->removable = 1;
#ifdef CONFIG_PPC #ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */ /* kludge for Apple PowerBook internal zip */
if (!strstr(id->model, "CD-ROM") && if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
strstr(id->model, "ZIP")) {
printk(KERN_CONT "FLOPPY"); printk(KERN_CONT "FLOPPY");
type = ide_floppy; type = ide_floppy;
break; break;
...@@ -217,18 +212,15 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -217,18 +212,15 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
* Not an ATAPI device: looks like a "regular" hard disk * Not an ATAPI device: looks like a "regular" hard disk
*/ */
/* is_cfa = ata_id_is_cfa(id);
* 0x848a = CompactFlash device
* These are *not* removable in Linux definition of the term
*/
if ((id->config != 0x848a) && (id->config & (1<<7))) /* 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->removable = 1;
drive->media = ide_disk; drive->media = ide_disk;
printk(KERN_CONT "%s DISK drive\n", printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
(id->config == 0x848a) ? "CFA" : "ATA");
return; return;
...@@ -268,7 +260,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) ...@@ -268,7 +260,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
if (io_ports->ctl_addr) { if (io_ports->ctl_addr) {
a = tp_ops->read_altstatus(hwif); a = tp_ops->read_altstatus(hwif);
s = tp_ops->read_status(hwif); s = tp_ops->read_status(hwif);
if ((a ^ s) & ~INDEX_STAT) if ((a ^ s) & ~ATA_IDX)
/* ancient Seagate drives, broken interfaces */ /* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) " printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
"instead of ALTSTATUS(0x%02x)\n", "instead of ALTSTATUS(0x%02x)\n",
...@@ -281,7 +273,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) ...@@ -281,7 +273,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi /* set features register for atapi
* identify command to be sure of reply * identify command to be sure of reply
*/ */
if (cmd == WIN_PIDENTIFY) { if (cmd == ATA_CMD_ID_ATAPI) {
ide_task_t task; ide_task_t task;
memset(&task, 0, sizeof(task)); memset(&task, 0, sizeof(task));
...@@ -294,24 +286,16 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) ...@@ -294,24 +286,16 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* ask drive for ID */ /* ask drive for ID */
tp_ops->exec_command(hwif, cmd); tp_ops->exec_command(hwif, cmd);
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies;
do {
if (time_after(jiffies, timeout)) {
/* drive timed-out */
return 1;
}
/* give drive a breather */
msleep(50);
s = use_altstatus ? tp_ops->read_altstatus(hwif)
: tp_ops->read_status(hwif);
} while (s & BUSY_STAT);
/* wait for IRQ and DRQ_STAT */ if (ide_busy_sleep(hwif, timeout, use_altstatus))
return 1;
/* wait for IRQ and ATA_DRQ */
msleep(50); msleep(50);
s = tp_ops->read_status(hwif); s = tp_ops->read_status(hwif);
if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) { if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
unsigned long flags; unsigned long flags;
/* local CPU only; some systems need this */ /* local CPU only; some systems need this */
...@@ -387,19 +371,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) ...@@ -387,19 +371,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
return retval; return retval;
} }
static int ide_busy_sleep(ide_hwif_t *hwif) int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
{ {
unsigned long timeout = jiffies + WAIT_WORSTCASE;
u8 stat; u8 stat;
timeout += jiffies;
do { do {
msleep(50); msleep(50); /* give drive a breather */
stat = hwif->tp_ops->read_status(hwif); stat = altstatus ? hwif->tp_ops->read_altstatus(hwif)
if ((stat & BUSY_STAT) == 0) : hwif->tp_ops->read_status(hwif);
if ((stat & ATA_BUSY) == 0)
return 0; return 0;
} while (time_before(jiffies, timeout)); } while (time_before(jiffies, timeout));
return 1; return 1; /* drive timed-out */
} }
static u8 ide_read_device(ide_drive_t *drive) static u8 ide_read_device(ide_drive_t *drive)
...@@ -444,13 +430,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) ...@@ -444,13 +430,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
if (drive->present) { if (drive->present) {
/* avoid waiting for inappropriate probes */ /* avoid waiting for inappropriate probes */
if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) if (drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
return 4; return 4;
} }
#ifdef DEBUG #ifdef DEBUG
printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
drive->name, drive->present, drive->media, drive->name, drive->present, drive->media,
(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
#endif #endif
/* needed for some systems /* needed for some systems
...@@ -464,7 +450,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) ...@@ -464,7 +450,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
if (drive->select.b.unit != 0) { if (drive->select.b.unit != 0) {
/* exit with drive0 selected */ /* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]); SELECT_DRIVE(&hwif->drives[0]);
/* allow BUSY_STAT to assert & clear */ /* allow ATA_BUSY to assert & clear */
msleep(50); msleep(50);
} }
/* no i/f present: mmm.. this should be a 4 -ml */ /* no i/f present: mmm.. this should be a 4 -ml */
...@@ -473,8 +459,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) ...@@ -473,8 +459,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif); stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, READY_STAT, BUSY_STAT) || if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
drive->present || cmd == WIN_PIDENTIFY) { drive->present || cmd == ATA_CMD_ID_ATAPI) {
/* send cmd and wait */ /* send cmd and wait */
if ((rc = try_to_identify(drive, cmd))) { if ((rc = try_to_identify(drive, cmd))) {
/* failed: try again */ /* failed: try again */
...@@ -483,17 +469,17 @@ static int do_probe (ide_drive_t *drive, u8 cmd) ...@@ -483,17 +469,17 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif); stat = tp_ops->read_status(hwif);
if (stat == (BUSY_STAT | READY_STAT)) if (stat == (ATA_BUSY | ATA_DRDY))
return 4; return 4;
if (rc == 1 && cmd == WIN_PIDENTIFY) { if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
printk(KERN_ERR "%s: no response (status = 0x%02x), " printk(KERN_ERR "%s: no response (status = 0x%02x), "
"resetting drive\n", drive->name, stat); "resetting drive\n", drive->name, stat);
msleep(50); msleep(50);
SELECT_DRIVE(drive); SELECT_DRIVE(drive);
msleep(50); msleep(50);
tp_ops->exec_command(hwif, WIN_SRST); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
(void)ide_busy_sleep(hwif); (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
rc = try_to_identify(drive, cmd); rc = try_to_identify(drive, cmd);
} }
...@@ -526,13 +512,14 @@ static void enable_nest (ide_drive_t *drive) ...@@ -526,13 +512,14 @@ static void enable_nest (ide_drive_t *drive)
const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat; u8 stat;
printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model); printk(KERN_INFO "%s: enabling %s -- ",
hwif->name, (char *)&drive->id[ATA_ID_PROD]);
SELECT_DRIVE(drive); SELECT_DRIVE(drive);
msleep(50); msleep(50);
tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST); tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
if (ide_busy_sleep(hwif)) { if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
printk(KERN_CONT "failed (timeout)\n"); printk(KERN_CONT "failed (timeout)\n");
return; return;
} }
...@@ -545,12 +532,6 @@ static void enable_nest (ide_drive_t *drive) ...@@ -545,12 +532,6 @@ static void enable_nest (ide_drive_t *drive)
printk(KERN_CONT "failed (status = 0x%02x)\n", stat); printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
else else
printk(KERN_CONT "success\n"); printk(KERN_CONT "success\n");
/* if !(success||timed-out) */
if (do_probe(drive, WIN_IDENTIFY) >= 2) {
/* look for ATAPI device */
(void) do_probe(drive, WIN_PIDENTIFY);
}
} }
/** /**
...@@ -567,6 +548,8 @@ static void enable_nest (ide_drive_t *drive) ...@@ -567,6 +548,8 @@ static void enable_nest (ide_drive_t *drive)
static inline u8 probe_for_drive (ide_drive_t *drive) static inline u8 probe_for_drive (ide_drive_t *drive)
{ {
char *m;
/* /*
* In order to keep things simple we have an id * In order to keep things simple we have an id
* block for all drives at all times. If the device * block for all drives at all times. If the device
...@@ -576,29 +559,34 @@ static inline u8 probe_for_drive (ide_drive_t *drive) ...@@ -576,29 +559,34 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
* Also note that 0 everywhere means "can't do X" * Also note that 0 everywhere means "can't do X"
*/ */
drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL); drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
drive->id_read = 0; drive->id_read = 0;
if(drive->id == NULL) if(drive->id == NULL)
{ {
printk(KERN_ERR "ide: out of memory for id data.\n"); printk(KERN_ERR "ide: out of memory for id data.\n");
return 0; return 0;
} }
strcpy(drive->id->model, "UNKNOWN");
m = (char *)&drive->id[ATA_ID_PROD];
strcpy(m, "UNKNOWN");
/* skip probing? */ /* skip probing? */
if (!drive->noprobe) if (!drive->noprobe) {
{ retry:
/* if !(success||timed-out) */ /* if !(success||timed-out) */
if (do_probe(drive, WIN_IDENTIFY) >= 2) { if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
/* look for ATAPI device */ /* look for ATAPI device */
(void) do_probe(drive, WIN_PIDENTIFY); (void)do_probe(drive, ATA_CMD_ID_ATAPI);
}
if (!drive->present) if (!drive->present)
/* drive not found */ /* drive not found */
return 0; return 0;
if (strstr(drive->id->model, "E X A B Y T E N E S T"))
if (strstr(m, "E X A B Y T E N E S T")) {
enable_nest(drive); enable_nest(drive);
goto retry;
}
/* identification failed? */ /* identification failed? */
if (!drive->id_read) { if (!drive->id_read) {
if (drive->media == ide_disk) { if (drive->media == ide_disk) {
...@@ -740,36 +728,38 @@ static int ide_port_wait_ready(ide_hwif_t *hwif) ...@@ -740,36 +728,38 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
/** /**
* ide_undecoded_slave - look for bad CF adapters * ide_undecoded_slave - look for bad CF adapters
* @drive1: drive * @dev1: slave device
* *
* Analyse the drives on the interface and attempt to decide if we * Analyse the drives on the interface and attempt to decide if we
* have the same drive viewed twice. This occurs with crap CF adapters * have the same drive viewed twice. This occurs with crap CF adapters
* and PCMCIA sometimes. * and PCMCIA sometimes.
*/ */
void ide_undecoded_slave(ide_drive_t *drive1) void ide_undecoded_slave(ide_drive_t *dev1)
{ {
ide_drive_t *drive0 = &drive1->hwif->drives[0]; ide_drive_t *dev0 = &dev1->hwif->drives[0];
if ((drive1->dn & 1) == 0 || drive0->present == 0) if ((dev1->dn & 1) == 0 || dev0->present == 0)
return; return;
/* If the models don't match they are not the same product */ /* If the models don't match they are not the same product */
if (strcmp(drive0->id->model, drive1->id->model)) if (strcmp((char *)&dev0->id[ATA_ID_PROD],
(char *)&dev1->id[ATA_ID_PROD]))
return; return;
/* Serial numbers do not match */ /* Serial numbers do not match */
if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20)) if (strncmp((char *)&dev0->id[ATA_ID_SERNO],
(char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN))
return; return;
/* No serial number, thankfully very rare for CF */ /* No serial number, thankfully very rare for CF */
if (drive0->id->serial_no[0] == 0) if (*(char *)&dev0->id[ATA_ID_SERNO] == 0)
return; return;
/* Appears to be an IDE flash adapter with decode bugs */ /* Appears to be an IDE flash adapter with decode bugs */
printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n"); printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
drive1->present = 0; dev1->present = 0;
} }
EXPORT_SYMBOL_GPL(ide_undecoded_slave); EXPORT_SYMBOL_GPL(ide_undecoded_slave);
...@@ -853,7 +843,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ...@@ -853,7 +843,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
drive->no_io_32bit = 1; drive->no_io_32bit = 1;
else else
drive->no_io_32bit = drive->id->dword_io ? 1 : 0; drive->no_io_32bit = drive->id[ATA_ID_DWORD_IO] ? 1 : 0;
} }
} }
...@@ -1037,11 +1027,6 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1037,11 +1027,6 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup; ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL; ide_hwif_t *match = NULL;
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
BUG_ON(hwif == NULL);
mutex_lock(&ide_cfg_mtx); mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL; hwif->hwgroup = NULL;
#if MAX_HWIFS > 1 #if MAX_HWIFS > 1
...@@ -1116,7 +1101,8 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1116,7 +1101,8 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED; sa = IRQF_SHARED;
#endif /* __mc68000__ */ #endif /* __mc68000__ */
if (IDE_CHIPSET_IS_PCI(hwif->chipset)) if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
hwif->chipset == ide_ali14xx)
sa = IRQF_SHARED; sa = IRQF_SHARED;
if (io_ports->ctl_addr) if (io_ports->ctl_addr)
...@@ -1344,8 +1330,6 @@ static void hwif_register_devices(ide_hwif_t *hwif) ...@@ -1344,8 +1330,6 @@ static void hwif_register_devices(ide_hwif_t *hwif)
if (!drive->present) if (!drive->present)
continue; continue;
ide_add_generic_settings(drive);
snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
dev->parent = &hwif->gendev; dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type; dev->bus = &ide_bus_type;
...@@ -1602,8 +1586,10 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, ...@@ -1602,8 +1586,10 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
if (hws[0]) if (hws[0])
host->dev[0] = hws[0]->dev; host->dev[0] = hws[0]->dev;
if (d) if (d) {
host->init_chipset = d->init_chipset;
host->host_flags = d->host_flags; host->host_flags = d->host_flags;
}
return host; return host;
} }
......
...@@ -12,14 +12,6 @@ ...@@ -12,14 +12,6 @@
* "settings" files. e.g. "cat /proc/ide0/hda/settings" * "settings" files. e.g. "cat /proc/ide0/hda/settings"
* To write a new value "val" into a specific setting "name", use: * To write a new value "val" into a specific setting "name", use:
* echo "name:val" >/proc/ide/ide0/hda/settings * echo "name:val" >/proc/ide/ide0/hda/settings
*
* Also useful, "cat /proc/ide0/hda/[identify, smart_values,
* smart_thresholds, capabilities]" will issue an IDENTIFY /
* PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS /
* SENSE CAPABILITIES command to /dev/hda, and then dump out the
* returned data as 256 16-bit words. The "hdparm" utility will
* be updated someday soon to use this mechanism.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -31,7 +23,6 @@ ...@@ -31,7 +23,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -109,13 +100,14 @@ static int proc_ide_read_identify ...@@ -109,13 +100,14 @@ static int proc_ide_read_identify
err = taskfile_lib_get_identify(drive, page); err = taskfile_lib_get_identify(drive, page);
if (!err) { if (!err) {
char *out = ((char *)page) + (SECTOR_WORDS * 4); char *out = (char *)page + SECTOR_SIZE;
page = out; page = out;
do { do {
out += sprintf(out, "%04x%c", out += sprintf(out, "%04x%c",
le16_to_cpup(val), (++i & 7) ? ' ' : '\n'); le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
val += 1; val += 1;
} while (i < (SECTOR_WORDS * 2)); } while (i < SECTOR_SIZE / 2);
len = out - page; len = out - page;
} }
} }
...@@ -123,140 +115,25 @@ static int proc_ide_read_identify ...@@ -123,140 +115,25 @@ static int proc_ide_read_identify
} }
/** /**
* __ide_add_setting - add an ide setting option * ide_find_setting - find a specific setting
* @drive: drive to use * @st: setting table pointer
* @name: setting name
* @rw: true if the function is read write
* @data_type: type of data
* @min: range minimum
* @max: range maximum
* @mul_factor: multiplication scale
* @div_factor: divison scale
* @data: private data field
* @set: setting
* @auto_remove: setting auto removal flag
*
* Removes the setting named from the device if it is present.
* The function takes the settings_lock to protect against
* parallel changes. This function must not be called from IRQ
* context. Returns 0 on success or -1 on failure.
*
* BUGS: This code is seriously over-engineered. There is also
* magic about how the driver specific features are setup. If
* a driver is attached we assume the driver settings are auto
* remove.
*/
static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
mutex_lock(&ide_setting_mtx);
while ((*p) && strcmp((*p)->name, name) < 0)
p = &((*p)->next);
if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
goto abort;
if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
goto abort;
strcpy(setting->name, name);
setting->rw = rw;
setting->data_type = data_type;
setting->min = min;
setting->max = max;
setting->mul_factor = mul_factor;
setting->div_factor = div_factor;
setting->data = data;
setting->set = set;
setting->next = *p;
if (auto_remove)
setting->auto_remove = 1;
*p = setting;
mutex_unlock(&ide_setting_mtx);
return 0;
abort:
mutex_unlock(&ide_setting_mtx);
kfree(setting);
return -1;
}
int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
{
return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
}
EXPORT_SYMBOL(ide_add_setting);
/**
* __ide_remove_setting - remove an ide setting option
* @drive: drive to use
* @name: setting name
*
* Removes the setting named from the device if it is present.
* The caller must hold the setting semaphore.
*/
static void __ide_remove_setting(ide_drive_t *drive, char *name)
{
ide_settings_t **p, *setting;
p = (ide_settings_t **) &drive->settings;
while ((*p) && strcmp((*p)->name, name))
p = &((*p)->next);
setting = (*p);
if (setting == NULL)
return;
(*p) = setting->next;
kfree(setting->name);
kfree(setting);
}
/**
* auto_remove_settings - remove driver specific settings
* @drive: drive
*
* Automatically remove all the driver specific settings for this
* drive. This function may not be called from IRQ context. The
* caller must hold ide_setting_mtx.
*/
static void auto_remove_settings(ide_drive_t *drive)
{
ide_settings_t *setting;
repeat:
setting = drive->settings;
while (setting) {
if (setting->auto_remove) {
__ide_remove_setting(drive, setting->name);
goto repeat;
}
setting = setting->next;
}
}
/**
* ide_find_setting_by_name - find a drive specific setting
* @drive: drive to scan
* @name: setting name * @name: setting name
* *
* Scan's the device setting table for a matching entry and returns * Scan's the setting table for a matching entry and returns
* this or NULL if no entry is found. The caller must hold the * this or NULL if no entry is found. The caller must hold the
* setting semaphore * setting semaphore
*/ */
static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) static
const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st,
char *name)
{ {
ide_settings_t *setting = drive->settings; while (st->name) {
if (strcmp(st->name, name) == 0)
while (setting) {
if (strcmp(setting->name, name) == 0)
break; break;
setting = setting->next; st++;
} }
return setting; return st->name ? st : NULL;
} }
/** /**
...@@ -272,26 +149,20 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) ...@@ -272,26 +149,20 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* be told apart * be told apart
*/ */
static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) static int ide_read_setting(ide_drive_t *drive,
const struct ide_proc_devset *setting)
{ {
int val = -EINVAL; const struct ide_devset *ds = setting->setting;
unsigned long flags; int val = -EINVAL;
if (ds->get) {
unsigned long flags;
if ((setting->rw & SETTING_READ)) {
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
switch (setting->data_type) { val = ds->get(drive);
case TYPE_BYTE:
val = *((u8 *) setting->data);
break;
case TYPE_SHORT:
val = *((u16 *) setting->data);
break;
case TYPE_INT:
val = *((u32 *) setting->data);
break;
}
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
return val; return val;
} }
...@@ -313,33 +184,23 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) ...@@ -313,33 +184,23 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* The current scheme of polling is kludgy, though safe enough. * The current scheme of polling is kludgy, though safe enough.
*/ */
static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) static int ide_write_setting(ide_drive_t *drive,
const struct ide_proc_devset *setting, int val)
{ {
const struct ide_devset *ds = setting->setting;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
if (setting->set) if (!ds->set)
return setting->set(drive, val);
if (!(setting->rw & SETTING_WRITE))
return -EPERM; return -EPERM;
if (val < setting->min || val > setting->max) if ((ds->flags & DS_SYNC)
&& (val < setting->min || val > setting->max))
return -EINVAL; return -EINVAL;
if (ide_spin_wait_hwgroup(drive)) return ide_devset_execute(drive, ds, val);
return -EBUSY;
switch (setting->data_type) {
case TYPE_BYTE:
*((u8 *) setting->data) = val;
break;
case TYPE_SHORT:
*((u16 *) setting->data) = val;
break;
case TYPE_INT:
*((u32 *) setting->data) = val;
break;
}
spin_unlock_irq(&ide_lock);
return 0;
} }
ide_devset_get(xfer_rate, current_speed);
static int set_xfer_rate (ide_drive_t *drive, int arg) static int set_xfer_rate (ide_drive_t *drive, int arg)
{ {
ide_task_t task; ide_task_t task;
...@@ -349,7 +210,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) ...@@ -349,7 +210,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
return -EINVAL; return -EINVAL;
memset(&task, 0, sizeof(task)); memset(&task, 0, sizeof(task));
task.tf.command = WIN_SETFEATURES; task.tf.command = ATA_CMD_SET_FEATURES;
task.tf.feature = SETFEATURES_XFER; task.tf.feature = SETFEATURES_XFER;
task.tf.nsect = (u8)arg; task.tf.nsect = (u8)arg;
task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
...@@ -364,29 +225,23 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) ...@@ -364,29 +225,23 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
return err; return err;
} }
/** ide_devset_rw(current_speed, xfer_rate);
* ide_add_generic_settings - generic ide settings ide_devset_rw_field(init_speed, init_speed);
* @drive: drive being configured ide_devset_rw_field(nice1, nice1);
* ide_devset_rw_field(number, dn);
* Add the generic parts of the system settings to the /proc files.
* The caller must not be holding the ide_setting_mtx. static const struct ide_proc_devset ide_generic_settings[] = {
*/ IDE_PROC_DEVSET(current_speed, 0, 70),
IDE_PROC_DEVSET(init_speed, 0, 70),
void ide_add_generic_settings (ide_drive_t *drive) IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)),
{ IDE_PROC_DEVSET(keepsettings, 0, 1),
/* IDE_PROC_DEVSET(nice1, 0, 1),
* drive setting name read/write access data type min max mul_factor div_factor data pointer set function IDE_PROC_DEVSET(number, 0, 3),
*/ IDE_PROC_DEVSET(pio_mode, 0, 255),
__ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); IDE_PROC_DEVSET(unmaskirq, 0, 1),
__ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); IDE_PROC_DEVSET(using_dma, 0, 1),
__ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); { 0 },
__ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); };
__ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0);
__ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0);
__ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0);
__ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0);
__ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0);
}
static void proc_ide_settings_warn(void) static void proc_ide_settings_warn(void)
{ {
...@@ -403,19 +258,32 @@ static void proc_ide_settings_warn(void) ...@@ -403,19 +258,32 @@ static void proc_ide_settings_warn(void)
static int proc_ide_read_settings static int proc_ide_read_settings
(char *page, char **start, off_t off, int count, int *eof, void *data) (char *page, char **start, off_t off, int count, int *eof, void *data)
{ {
const struct ide_proc_devset *setting, *g, *d;
const struct ide_devset *ds;
ide_drive_t *drive = (ide_drive_t *) data; ide_drive_t *drive = (ide_drive_t *) data;
ide_settings_t *setting = (ide_settings_t *) drive->settings;
char *out = page; char *out = page;
int len, rc, mul_factor, div_factor; int len, rc, mul_factor, div_factor;
proc_ide_settings_warn(); proc_ide_settings_warn();
mutex_lock(&ide_setting_mtx); mutex_lock(&ide_setting_mtx);
g = ide_generic_settings;
d = drive->settings;
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
while (setting) { while (g->name || (d && d->name)) {
mul_factor = setting->mul_factor; /* read settings in the alphabetical order */
div_factor = setting->div_factor; if (g->name && d && d->name) {
if (strcmp(d->name, g->name) < 0)
setting = d++;
else
setting = g++;
} else if (d && d->name) {
setting = d++;
} else
setting = g++;
mul_factor = setting->mulf ? setting->mulf(drive) : 1;
div_factor = setting->divf ? setting->divf(drive) : 1;
out += sprintf(out, "%-24s", setting->name); out += sprintf(out, "%-24s", setting->name);
rc = ide_read_setting(drive, setting); rc = ide_read_setting(drive, setting);
if (rc >= 0) if (rc >= 0)
...@@ -423,12 +291,12 @@ static int proc_ide_read_settings ...@@ -423,12 +291,12 @@ static int proc_ide_read_settings
else else
out += sprintf(out, "%-16s", "write-only"); out += sprintf(out, "%-16s", "write-only");
out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
if (setting->rw & SETTING_READ) ds = setting->setting;
if (ds->get)
out += sprintf(out, "r"); out += sprintf(out, "r");
if (setting->rw & SETTING_WRITE) if (ds->set)
out += sprintf(out, "w"); out += sprintf(out, "w");
out += sprintf(out, "\n"); out += sprintf(out, "\n");
setting = setting->next;
} }
len = out - page; len = out - page;
mutex_unlock(&ide_setting_mtx); mutex_unlock(&ide_setting_mtx);
...@@ -442,9 +310,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, ...@@ -442,9 +310,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
{ {
ide_drive_t *drive = (ide_drive_t *) data; ide_drive_t *drive = (ide_drive_t *) data;
char name[MAX_LEN + 1]; char name[MAX_LEN + 1];
int for_real = 0; int for_real = 0, mul_factor, div_factor;
unsigned long n; unsigned long n;
ide_settings_t *setting;
const struct ide_proc_devset *setting;
char *buf, *s; char *buf, *s;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -512,13 +381,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, ...@@ -512,13 +381,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
} }
mutex_lock(&ide_setting_mtx); mutex_lock(&ide_setting_mtx);
setting = ide_find_setting_by_name(drive, name); /* generic settings first, then driver specific ones */
setting = ide_find_setting(ide_generic_settings, name);
if (!setting) { if (!setting) {
mutex_unlock(&ide_setting_mtx); if (drive->settings)
goto parse_error; setting = ide_find_setting(drive->settings, name);
if (!setting) {
mutex_unlock(&ide_setting_mtx);
goto parse_error;
}
}
if (for_real) {
mul_factor = setting->mulf ? setting->mulf(drive) : 1;
div_factor = setting->divf ? setting->divf(drive) : 1;
ide_write_setting(drive, setting, val * div_factor / mul_factor);
} }
if (for_real)
ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
mutex_unlock(&ide_setting_mtx); mutex_unlock(&ide_setting_mtx);
} }
} while (!for_real++); } while (!for_real++);
...@@ -561,11 +438,10 @@ static int proc_ide_read_dmodel ...@@ -561,11 +438,10 @@ static int proc_ide_read_dmodel
(char *page, char **start, off_t off, int count, int *eof, void *data) (char *page, char **start, off_t off, int count, int *eof, void *data)
{ {
ide_drive_t *drive = (ide_drive_t *) data; ide_drive_t *drive = (ide_drive_t *) data;
struct hd_driveid *id = drive->id; char *m = (char *)&drive->id[ATA_ID_PROD];
int len; int len;
len = sprintf(page, "%.40s\n", len = sprintf(page, "%.40s\n", m[0] ? m : "(none)");
(id && id->model[0]) ? (char *)id->model : "(none)");
PROC_IDE_READ_RETURN(page, start, off, count, eof, len); PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
} }
...@@ -690,6 +566,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t ...@@ -690,6 +566,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
{ {
mutex_lock(&ide_setting_mtx);
drive->settings = driver->settings;
mutex_unlock(&ide_setting_mtx);
ide_add_proc_entries(drive->proc, driver->proc, drive); ide_add_proc_entries(drive->proc, driver->proc, drive);
} }
...@@ -726,7 +606,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) ...@@ -726,7 +606,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* OTOH both ide_{read,write}_setting are only ever used under * OTOH both ide_{read,write}_setting are only ever used under
* ide_setting_mtx. * ide_setting_mtx.
*/ */
auto_remove_settings(drive); drive->settings = NULL;
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx); mutex_unlock(&ide_setting_mtx);
} }
......
此差异已折叠。
此差异已折叠。
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -78,15 +77,15 @@ EXPORT_SYMBOL_GPL(ide_timing_find_mode); ...@@ -78,15 +77,15 @@ EXPORT_SYMBOL_GPL(ide_timing_find_mode);
u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio) u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
u16 cycle = 0; u16 cycle = 0;
if (id->field_valid & 2) { if (id[ATA_ID_FIELD_VALID] & 2) {
if (id->capability & 8) if (ata_id_has_iordy(drive->id))
cycle = id->eide_pio_iordy; cycle = id[ATA_ID_EIDE_PIO_IORDY];
else else
cycle = id->eide_pio; cycle = id[ATA_ID_EIDE_PIO];
/* conservative "downgrade" for all pre-ATA2 drives */ /* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3 && cycle < t->cycle) if (pio < 3 && cycle < t->cycle)
...@@ -138,7 +137,7 @@ EXPORT_SYMBOL_GPL(ide_timing_merge); ...@@ -138,7 +137,7 @@ EXPORT_SYMBOL_GPL(ide_timing_merge);
int ide_timing_compute(ide_drive_t *drive, u8 speed, int ide_timing_compute(ide_drive_t *drive, u8 speed,
struct ide_timing *t, int T, int UT) struct ide_timing *t, int T, int UT)
{ {
struct hd_driveid *id = drive->id; u16 *id = drive->id;
struct ide_timing *s, p; struct ide_timing *s, p;
/* /*
...@@ -157,16 +156,15 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed, ...@@ -157,16 +156,15 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed,
* If the drive is an EIDE drive, it can tell us it needs extended * If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing. * PIO/MWDMA cycle timing.
*/ */
if (id && id->field_valid & 2) { /* EIDE drive */ if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));
if (speed <= XFER_PIO_2) if (speed <= XFER_PIO_2)
p.cycle = p.cyc8b = id->eide_pio; p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
else if (speed <= XFER_PIO_5) else if (speed <= XFER_PIO_5)
p.cycle = p.cyc8b = id->eide_pio_iordy; p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
p.cycle = id->eide_dma_min; p.cycle = id[ATA_ID_EIDE_DMA_MIN];
ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B); ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
} }
......
此差异已折叠。
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/zorro.h> #include <linux/zorro.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/zorro.h> #include <linux/zorro.h>
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ide.h> #include <linux/ide.h>
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
/* /*
......
此差异已折叠。
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册