you can then use this emulation together with an appropriate SCSI
device driver. In order to do this, say Y here and to "SCSI support"
and "SCSI generic support", below. You must then provide the kernel
- command line "hdx=scsi" (try "man bootparam" or see the
+ command line "hdx=ide-scsi" (try "man bootparam" or see the
documentation of your boot loader (lilo or loadlin) about how to
pass options to the kernel at boot time) for devices if you want the
native EIDE sub-drivers to skip over the native support, so that
CONFIG_BLK_DEV_PDC4030
This driver provides support for the secondary IDE interface and
- cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver
- is known to incur timeouts/retries during heavy I/O to drives
- attached to the secondary interface. CD-ROM and TAPE devices are
- not supported yet. This driver is enabled at runtime using the
- "ide0=dc4030" kernel boot parameter. See the
- <file:Documentation/ide.txt> and <file:drivers/ide/pdc4030.c> files
- for more info.
+ cache of the original Promise IDE chipsets, e.g. DC4030 and DC5030.
+ It is nothing to do with the later range of Promise UDMA chipsets -
+ see the PDC_202XX support for these. CD-ROM and TAPE devices are not
+ supported (and probably never will be since I don't think the cards
+ support them). This driver is enabled at runtime using the "ide0=dc4030"
+ or "ide1=dc4030" kernel boot parameter. See the
+ <file:drivers/ide/pdc4030.c> file for more info.
CONFIG_BLK_DEV_QD65XX
This driver is enabled at runtime using the "ide0=qd65xx" kernel
devices (hard disks, CD-ROM drives, etc.) that are connected to the
builtin IDE interface.
+CONFIG_BLK_DEV_Q40IDE
+ Enable the on-board IDE controller in the Q40/Q60. This should
+ normally be on; disable it only if you are running a custom hard
+ drive subsystem through an expansion card.
+
CONFIG_BLK_DEV_IDE_ICSIDE
On Acorn systems, say Y here if you wish to use the ICS IDE
interface card. This is not required for ICS partition support.
int log = 0;
/* FIXME --mdcki */
struct packet_command *pc = (struct packet_command *) rq->special;
- struct packet_command *failed_command = (struct packet_command *) pc->sense;
+ struct packet_command *failed_command = pc->failed_command;
+
+ /* Decode sense data from drive */
struct request_sense *sense = (struct request_sense *) (pc->buffer - rq->cmd[4]);
unsigned char fail_cmd;
if (sense == NULL)
sense = &info->sense_data;
- memset(pc, 0, sizeof(struct packet_command));
+ memset(pc, 0, sizeof(*pc));
pc->buffer = (void *) sense;
pc->buflen = 18;
- pc->sense = (struct request_sense *) failed_command;
+ pc->failed_command = failed_command;
/* stuff the sense request in front of our current request */
rq = &info->request_sense_request;
pc->stat = 1;
cdrom_end_request(drive, 1);
*startstop = ide_error (drive, "request sense failure", stat);
+
return 1;
} else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
/* All other functions, except for READ. */
pc->stat = 1;
cdrom_end_request(drive, 1);
+ /* FIXME: this is the only place where pc->sense get's used.
+ * Think hard about how to get rid of it...
+ */
+
if ((stat & ERR_STAT) != 0)
cdrom_queue_request_sense(drive, wait, pc->sense, pc);
} else if (rq->flags & REQ_CMD) {
return startstop;
if (info->dma) {
- if (info->cmd == READ) {
+ if (info->cmd == READ)
info->dma = !drive->channel->dmaproc(ide_dma_read, drive);
- } else if (info->cmd == WRITE) {
+ else if (info->cmd == WRITE)
info->dma = !drive->channel->dmaproc(ide_dma_write, drive);
- } else {
+ else
printk("ide-cd: DMA set, but not allowed\n");
- }
}
/* Set up the controller registers. */
- OUT_BYTE (info->dma, IDE_FEATURE_REG);
- OUT_BYTE (0, IDE_NSECTOR_REG);
- OUT_BYTE (0, IDE_SECTOR_REG);
+ OUT_BYTE(info->dma, IDE_FEATURE_REG);
+ OUT_BYTE(0, IDE_NSECTOR_REG);
+ OUT_BYTE(0, IDE_SECTOR_REG);
- OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
- OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
+ OUT_BYTE(xferlen & 0xff, IDE_LCYL_REG);
+ OUT_BYTE(xferlen >> 8 , IDE_HCYL_REG);
if (IDE_CONTROL_REG)
OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
if (info->dma)
- (void) drive->channel->dmaproc(ide_dma_begin, drive);
+ drive->channel->dmaproc(ide_dma_begin, drive);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
BUG_ON(HWGROUP(drive)->handler);
}
static
-int cdrom_queue_packet_command(ide_drive_t *drive, unsigned char *cmd, struct packet_command *pc)
+int cdrom_queue_packet_command(ide_drive_t *drive, unsigned char *cmd,
+ struct request_sense *sense, struct packet_command *pc)
{
- struct request_sense sense;
struct request rq;
int retries = 10;
memcpy(rq.cmd, cmd, CDROM_PACKET_SIZE);
-
- if (pc->sense == NULL)
- pc->sense = &sense;
-
/* Start of retry loop. */
do {
ide_init_drive_cmd(&rq);
if (ide_do_drive_cmd(drive, &rq, ide_wait)) {
printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n",
drive->name, rq.buffer[0], rq.buffer[1]);
+
/* FIXME: we should probably abort/retry or something */
+ if (sense) {
+
+ /* Decode the error here at least for error
+ * reporting to upper layers.!
+ */
+
+ }
}
if (pc->stat != 0) {
/* The request failed. Retry if it was due to a unit
attention status
(usually means media was changed). */
- struct request_sense *reqbuf = pc->sense;
- if (reqbuf->sense_key == UNIT_ATTENTION)
+ if (sense && sense->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change (drive);
- else if (reqbuf->sense_key == NOT_READY &&
- reqbuf->asc == 4 && reqbuf->ascq != 4) {
+ else if (sense && sense->sense_key == NOT_READY &&
+ sense->asc == 4 && sense->ascq != 4) {
/* The drive is in the process of loading
a disk. Retry, but wait a little to give
the drive time to complete the load. */
cmd[7] = cdi->sanyo_slot % 3;
#endif
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
pc.sense = sense;
cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
cmd[4] = lockflag ? 1 : 0;
- stat = cdrom_queue_packet_command(drive, cmd, &pc);
+ stat = cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
/* If we got an illegal field error, the drive
cmd[0] = GPCMD_START_STOP_UNIT;
cmd[4] = 0x02 + (ejectflag != 0);
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
cmd[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
pc.buflen = sizeof(capbuf);
- stat = cdrom_queue_packet_command(drive, cmd, &pc);
+ stat = cdrom_queue_packet_command(drive, cmd, sense, &pc);
if (stat == 0)
*capacity = 1 + be32_to_cpu(capbuf.lba);
cmd[8] = (buflen & 0xff);
cmd[9] = (format << 6);
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
cmd[7] = (buflen >> 8);
cmd[8] = (buflen & 0xff);
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
/* ATAPI cdrom drives are free to select the speed you request or any slower
cmd[5] = speed & 0xff;
}
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, sense, &pc);
}
static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]);
lba_to_msf(lba_end-1, &cmd[6], &cmd[7], &cmd[8]);
- return cdrom_queue_packet_command(drive, cmd, &pc);
+ return cdrom_queue_packet_command(drive, cmd, &sense, &pc);
}
static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
pc.quiet = cgc->quiet;
pc.timeout = cgc->timeout;
pc.sense = cgc->sense;
- cgc->stat = cdrom_queue_packet_command(drive, cgc->cmd, &pc);
+ cgc->stat = cdrom_queue_packet_command(drive, cgc->cmd, cgc->sense, &pc);
if (!cgc->stat)
cgc->buflen -= pc.buflen;
int quiet;
int timeout;
struct request_sense *sense;
+
+ /* This is currently used to pass failed commands through the request
+ * queue. Is this for asynchronos error reporting?
+ *
+ * Can we always be sure that this didn't valish from stack beneath us
+ * - we can't!
+ */
+
+ struct packet_command *failed_command;
};
/* Structure of a MSF cdrom address. */
}
/* Teardown mappings after DMA has completed. */
-void ide_destroy_dmatable (ide_drive_t *drive)
+void ide_destroy_dmatable(struct ata_device *d)
{
- struct pci_dev *dev = drive->channel->pci_dev;
- struct ata_request *ar = IDE_CUR_AR(drive);
+ struct pci_dev *dev = d->channel->pci_dev;
+ struct ata_request *ar = IDE_CUR_AR(d);
pci_unmap_sg(dev, ar->ar_sg_table, ar->ar_sg_nents, ar->ar_sg_ddir);
}
/*
- * linux/drivers/ide/ide-floppy.c Version 0.97.sv Jan 14 2001
+ * linux/drivers/ide/ide-floppy.c Version 0.99 Feb 24 2002
*
* Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2000 - 2001 Paul Bristow <paul@paulbristow.net>
+ * Copyright (C) 2000 - 2002 Paul Bristow <paul@paulbristow.net>
*/
/*
*
* This driver supports the following IDE floppy drives:
*
- * LS-120 SuperDisk
+ * LS-120/240 SuperDisk
* Iomega Zip 100/250
* Iomega PC Card Clik!/PocketZip
*
* bit was being deasserted by my IOMEGA ATAPI ZIP 100
* drive before the drive was actually ready.
* Ver 0.98a Oct 29 01 Expose delay value so we can play.
+ * Ver 0.99 Feb 24 02 Remove duplicate code, modify clik! detection code
+ * to support new PocketZip drives
*/
-#define IDEFLOPPY_VERSION "0.98a"
+#define IDEFLOPPY_VERSION "0.99"
#include <linux/config.h>
#include <linux/module.h>
*/
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive,
- &idefloppy_pc_intr, /* service routine for packet command */
- floppy->ticks, /* wait this long before "failing" */
+ &idefloppy_pc_intr, /* service routine for packet command */
+ floppy->ticks, /* wait this long before "failing" */
&idefloppy_transfer_pc2); /* fail == transfer_pc2 */
return ide_started;
* above fix. It makes nasty clicking noises without
* it, so please don't remove this.
*/
- if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) {
+ if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(&drive->queue, 64);
set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
}
/*
- *
- *
* linux/drivers/ide/ide-m8xx.c
*
+ * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
+ * Modified for direct IDE interface
+ * by Thomas Lange, thomas@corelatus.com
+ * Modified for direct IDE interface on 8xx without using the PCMCIA
+ * controller
+ * by Steven.Scholz@imc-berlin.de
+ * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups
+ * by Mathew Locke <mattl@mvista.com>
*/
#include <linux/config.h>
#define DEBUG_TASKFILE 0 /* unset when fixed */
#if DEBUG_TASKFILE
-#define DTF(x...) printk(x)
+#define DTF(x...) printk(##x)
#else
#define DTF(x...)
#endif
int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *args, byte *buf)
{
struct request rq;
- struct ata_request ar;
+ struct ata_request star;
+
+ ata_ar_init(drive, &star);
+
+ /* Don't put this request on free_req list after usage.
+ */
+ star.ar_flags |= ATA_AR_STATIC;
- ata_ar_init(drive, &ar);
init_taskfile_request(&rq);
rq.buffer = buf;
- memcpy(&ar.ar_task, args, sizeof(*args));
+ memcpy(&star.ar_task, args, sizeof(*args));
if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
rq.current_nr_sectors = rq.nr_sectors
= (args->hobfile.sector_count << 8)
| args->taskfile.sector_count;
- rq.special = &ar;
+ rq.special = ☆
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
* handle the unexpected interrupt
*/
do {
- if (hwif->irq == irq) {
- stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
- if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
- /* Try to not flood the console with msgs */
- static unsigned long last_msgtime, count;
- ++count;
- if (0 < (signed long)(jiffies - (last_msgtime + HZ))) {
- last_msgtime = jiffies;
- printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n",
- hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
- }
+ if (hwif->irq != irq)
+ continue;
+
+ stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
+ if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+ /* Try to not flood the console with msgs */
+ static unsigned long last_msgtime;
+ static int count;
+ ++count;
+ if (time_after(jiffies, last_msgtime + HZ)) {
+ last_msgtime = jiffies;
+ printk("%s%s: unexpected interrupt, status=0x%02x, count=%d\n",
+ hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
}
}
- } while ((hwif = hwif->next) != hwgroup->hwif);
+ hwif = hwif->next;
+ } while (hwif != hwgroup->hwif);
}
/*
goto out_lock;
if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
- printk("ide: unexpected interrupt\n");
+ printk(KERN_INFO "ide: unexpected interrupt %d %d\n", hwif->unit, irq);
+
/*
* Not expecting an interrupt from this drive.
* That means this could be:
#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
static byte it8172_dma_2_pio (byte xfer_rate);
static int it8172_tune_chipset (ide_drive_t *drive, byte speed);
-static int it8172_config_drive_for_dma (ide_drive_t *drive);
+static int it8172_config_chipset_for_dma (ide_drive_t *drive);
static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
#endif
void __init ide_init_it8172(struct ata_channel *channel);
static void it8172_tune_drive (ide_drive_t *drive, byte pio)
{
unsigned long flags;
- u16 master_data;
- u32 slave_data;
+ u16 drive_enables;
+ u32 drive_timing;
int is_slave = (&drive->channel->drives[1] == drive);
- int master_port = 0x40;
- int slave_port = 0x44;
-
- if (pio == 255)
- pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
- else
- pio = min_t(byte, pio, 4);
+
+ if (pio == 255)
+ pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
+ else
+ pio = min_t(byte, pio, 4);
pci_read_config_word(drive->channel->pci_dev, master_port, &master_data);
pci_read_config_dword(drive->channel->pci_dev, slave_port, &slave_data);
* FIX! The DIOR/DIOW pulse width and recovery times in port 0x44
* are being left at the default values of 8 PCI clocks (242 nsec
* for a 33 MHz clock). These can be safely shortened at higher
- * PIO modes.
+ * PIO modes. The DIOR/DIOW pulse width and recovery times only
+ * apply to PIO modes, not to the DMA modes.
*/
+ /*
+ * Enable port 0x44. The IT8172G spec is confused; it calls
+ * this register the "Slave IDE Timing Register", but in fact,
+ * it controls timing for both master and slave drives.
+ */
+ drive_enables |= 0x4000;
+
if (is_slave) {
- master_data |= 0x4000;
+ drive_enables &= 0xc006;
if (pio > 1)
- /* enable PPE and IE */
- master_data |= 0x0060;
+ /* enable prefetch and IORDY sample-point */
+ drive_enables |= 0x0060;
} else {
- master_data &= 0xc060;
+ drive_enables &= 0xc060;
if (pio > 1)
- /* enable PPE and IE */
- master_data |= 0x0006;
+ /* enable prefetch and IORDY sample-point */
+ drive_enables |= 0x0006;
}
save_flags(flags);
case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
case XFER_SW_DMA_2: break;
default: return -1;
}
return err;
}
-static int it8172_config_drive_for_dma(ide_drive_t *drive)
+static int it8172_config_chipset_for_dma(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
byte speed;
{
switch (func) {
case ide_dma_check:
- return ide_dmaproc((ide_dma_action_t)it8172_config_drive_for_dma(drive),
+ return ide_dmaproc((ide_dma_action_t)it8172_config_chipset_for_dma(drive),
drive);
default :
break;
/* -*- linux-c -*-
- * linux/drivers/ide/pdc4030.c Version 0.90 May 27, 1999
+ * linux/drivers/ide/pdc4030.c Version 0.92 Jan 15, 2002
*
- * Copyright (C) 1995-1999 Linus Torvalds & authors (see below)
+ * Copyright (C) 1995-2002 Linus Torvalds & authors (see below)
*/
/*
* Autodetection code added.
*
* Version 0.90 Transition to BETA code. No lost/unexpected interrupts
+ * Version 0.91 Bring in line with new bio code in 2.5.1
+ * Version 0.92 Update for IDE driver taskfile changes
*/
/*
* effects.
*/
-#define DEBUG_READ
-#define DEBUG_WRITE
+#undef DEBUG_READ
+#undef DEBUG_WRITE
#include <linux/types.h>
#include <linux/kernel.h>
#include "pdc4030.h"
+#if SUPPORT_VLB_SYNC != 1
+#error This driver will not work unless SUPPORT_VLB_SYNC is 1
+#endif
+
/*
* promise_selectproc() is invoked by ide.c
* in preparation for access to the specified drive.
hwif->selectproc = hwif2->selectproc = &promise_selectproc;
hwif->serialized = hwif2->serialized = 1;
-/* Shift the remaining interfaces down by one */
+/* Shift the remaining interfaces up by one */
for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
struct ata_channel *h = &ide_hwifs[i];
#ifdef DEBUG
- printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
+ printk(KERN_DEBUG "pdc4030: Shifting i/f %d values to i/f %d\n",i-1,i);
#endif
ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL);
memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports));
are distinguished by writing the drive number (0-3) to the
Feature register.
FIXME: Is promise_selectproc now redundant??
- */
- taskfile.feature = (drive->channel->unit << 1) + drive->select.b.unit;
+ */
+ taskfile.feature = (drive->channel->unit << 1) + drive->select.b.unit;
taskfile.sector_count = rq->nr_sectors;
taskfile.sector_number = block;
taskfile.low_cylinder = (block>>=8);
#define ATA_AR_QUEUED 1
#define ATA_AR_SETUP 2
#define ATA_AR_RETURN 4
+#define ATA_AR_STATIC 8
/*
* if turn-around time is longer than this, halve queue depth
static inline void ata_ar_put(ide_drive_t *drive, struct ata_request *ar)
{
- list_add(&ar->ar_queue, &drive->free_req);
+ if (!(ar->ar_flags & ATA_AR_STATIC))
+ list_add(&ar->ar_queue, &drive->free_req);
if (ar->ar_flags & ATA_AR_QUEUED) {
/* clear the tag */