diff options
Diffstat (limited to 'drivers')
73 files changed, 2074 insertions, 2452 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 59fe051957e..5d312dc9be9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -503,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) scsi_cmd[0] = ATA_16; 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[8] = args[1]; scsi_cmd[10] = 0x4f; diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 682243bf2e4..482c0c4b964 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -39,6 +39,7 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/blkpg.h> +#include <linux/ata.h> #include <linux/hdreg.h> #define REALLY_SLOW_IO @@ -370,7 +371,7 @@ repeat: struct hd_i_struct *disk = &hd_info[i]; disk->special_op = disk->recalibrate = 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) goto repeat; } else @@ -558,7 +559,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) { if (disk->recalibrate) { 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; } if (disk->head > 16) { @@ -631,13 +632,13 @@ repeat: if (blk_fs_request(req)) { switch (rq_data_dir(req)) { case READ: - hd_out(disk, nsect, sec, head, cyl, WIN_READ, + hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ, &read_intr); if (reset) goto repeat; break; case WRITE: - hd_out(disk, nsect, sec, head, cyl, WIN_WRITE, + hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_WRITE, &write_intr); if (reset) goto repeat; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 052879a6f85..b50b5dac95b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -131,29 +131,6 @@ config BLK_DEV_IDEDISK 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 tristate "PCMCIA IDE support" depends on PCMCIA diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 64e0ecdc4ed..308b8a12f31 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -4,8 +4,8 @@ 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-pio-blacklist.o +ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ + ide-taskfile.o ide-pio-blacklist.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o @@ -37,11 +37,12 @@ obj-$(CONFIG_IDE_GENERIC) += ide-generic.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-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.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_IDEFLOPPY) += ide-floppy.o ifeq ($(CONFIG_BLK_DEV_IDECS), y) ide-cs-core-y += legacy/ide-cs.o diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index df4af408395..70f5b164828 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -10,7 +10,6 @@ #include <linux/slab.h> #include <linux/blkdev.h> #include <linux/errno.h> -#include <linux/hdreg.h> #include <linux/ide.h> #include <linux/dma-mapping.h> #include <linux/device.h> @@ -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 * take care to note the values in the ID... */ - if (use_dma_info && drive->id->eide_dma_time > cycle_time) - cycle_time = drive->id->eide_dma_time; + if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time) + cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME]; drive->drive_data = cycle_time; diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 4fd91dcf1dc..122ed3c072f 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -27,7 +27,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/ioport.h> -#include <linux/hdreg.h> #include <linux/ide.h> #include <linux/delay.h> #include <linux/init.h> @@ -180,7 +179,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, val32 |= (t2i << (dev ? 8 : 0)); writel(val32, base + BK3710_DATRCVR); - if (mate && mate->present) { + if (mate) { u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); if (mode2 < mode) @@ -213,7 +212,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) palm_bk3710_setudmamode(base, is_slave, xferspeed - XFER_UDMA_0); } 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); } } @@ -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 */ 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); } diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 6f704628c27..2427c380b3d 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -584,7 +584,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) * This function executes the _STM ACPI method for the target channel. * * _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. */ 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.pointer = (u8 *)&hwif->acpidata->gtm; 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[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; /* Output buffer: _STM has no output */ diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index adf04f99cde..608c5bade92 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -14,12 +14,201 @@ #define debug_log(fmt, args...) do {} while (0) #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 */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), - 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; 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, if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 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) printk(KERN_ERR "%s: DMA %s error\n", 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, } /* No more interrupts */ - if ((stat & DRQ_STAT) == 0) { + if ((stat & ATA_DRQ) == 0) { debug_log("Packet command completed, %d bytes transferred\n", pc->xferred); @@ -65,10 +254,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, local_irq_enable_in_hardirq(); if (drive->media == ide_tape && !scsi && - (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE) - stat &= ~ERR_STAT; + (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) + 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 */ 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, cmd_finished: pc->error = 0; if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && - (stat & SEEK_STAT) == 0) { + (stat & ATA_DSC) == 0) { dsc_handle(drive); return ide_stopped; } @@ -117,17 +306,18 @@ cmd_finished: /* Get the number of bytes to transfer on this interrupt. */ 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__); 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 */ printk(KERN_ERR "%s: We wanted to %s, but the device wants us " "to %s!\n", drive->name, - (ireason & IO) ? "Write" : "Read", - (ireason & IO) ? "Read" : "Write"); + (ireason & ATAPI_IO) ? "Write" : "Read", + (ireason & ATAPI_IO) ? "Read" : "Write"); return ide_do_reset(drive); } @@ -171,9 +361,14 @@ cmd_finished: if ((drive->media == ide_floppy && !scsi && !pc->buf) || (drive->media == ide_tape && !scsi && pc->bh) || - (scsi && pc->sg)) - io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); - else + (scsi && pc->sg)) { + int done = io_buffers(drive, pc, bcount, + !!(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); /* Update the current position */ @@ -205,7 +400,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) { int retries = 100; |