Digital drives in the Expert series (by nature of really being IBM
drives).
- If you have such a drive, say Y here.
+ However, please, note that there are host chip controllers which will
+ not cooperate properly if TCQ is enabled. This may cause serious
+ data loss!
+
+ Since enabling TCQ doesn't appear to have any noticeable performance
+ impact on Linux: [feel free to correct me if you wish too please]
+
+ Generally say N here.
CONFIG_BLK_DEV_IDE_TCQ_DEPTH
Maximum size of commands to enable per-drive. Any value between 1
dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_bool ' ATA tagged command queueing (EXPERIMENTAL)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
+ dep_bool ' ATA tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
#include <linux/blkdev.h>
#include <linux/errno.h>
#include <linux/slab.h>
+#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
outsw(IDE_DATA_REG, buf + (n & ~0x03), 1);
}
+
+/*
+ * This function issues a special IDE device request onto the request queue.
+ *
+ * If action is ide_wait, then the rq is queued at the end of the request
+ * queue, and the function sleeps until it has been processed. This is for use
+ * when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then the rq is queued at the head of the request
+ * queue, displacing the currently-being-processed request and this function
+ * returns immediately without waiting for the new rq to be completed. This is
+ * VERY DANGEROUS, and is intended for careful use by the ATAPI tape/cdrom
+ * driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the request queue,
+ * and the function returns immediately without waiting for the new rq to be
+ * completed. This is again intended for careful use by the ATAPI tape/cdrom
+ * driver code.
+ */
+int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action)
+{
+ unsigned long flags;
+ struct ata_channel *ch = drive->channel;
+ unsigned int major = ch->major;
+ request_queue_t *q = &drive->queue;
+ struct list_head *queue_head = &q->queue_head;
+ DECLARE_COMPLETION(wait);
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (ch->chipset == ide_pdc4030 && rq->buffer)
+ return -ENOSYS; /* special drive cmds not supported */
+#endif
+ rq->errors = 0;
+ rq->rq_status = RQ_ACTIVE;
+ rq->rq_dev = mk_kdev(major, (drive->select.b.unit) << PARTN_BITS);
+ if (action == ide_wait)
+ rq->waiting = &wait;
+
+ spin_lock_irqsave(ch->lock, flags);
+
+ if (action == ide_preempt)
+ drive->rq = NULL;
+ else if (!blk_queue_empty(&drive->queue))
+ queue_head = queue_head->prev; /* ide_end and ide_wait */
+
+ __elv_add_request(q, rq, queue_head);
+
+ do_ide_request(q);
+
+ spin_unlock_irqrestore(ch->lock, flags);
+
+ if (action == ide_wait) {
+ wait_for_completion(&wait); /* wait for it to be serviced */
+ return rq->errors ? -EIO : 0; /* return -EIO if errors */
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(atapi_discard_data);
EXPORT_SYMBOL(atapi_write_zeros);
EXPORT_SYMBOL(atapi_init_pc);
ch->maskproc(drive);
}
+EXPORT_SYMBOL(ata_mask);
+
/*
* Check the state of the status register.
*/
EXPORT_SYMBOL(ata_status);
+/*
+ * This is used to check for the drive status on the IRQ handling code path.
+ */
+int ata_status_irq(struct ata_device *drive)
+{
+ if (test_bit(IDE_DMA, drive->channel->active))
+ return udma_irq_status(drive);
+
+ /* Need to guarantee 400ns since last command was issued?
+ */
+#ifdef CONFIG_IDEPCI_SHARE_IRQ
+
+ /*
+ * We do a passive status test under shared PCI interrupts on cards
+ * that truly share the ATA side interrupt, but may also share an
+ * interrupt with another pci card/device.
+ */
+
+ if (drive->channel->io_ports[IDE_CONTROL_OFFSET])
+ drive->status = IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]);
+
+ else
+#endif
+ ata_status(drive, 0, 0); /* Note: this may clear a pending IRQ! */
+
+ if (drive->status & BUSY_STAT)
+ return 0; /* drive busy: definitely not interrupting */
+ else
+ return 1; /* drive ready: *might* be interrupting */
+}
+
+EXPORT_SYMBOL(ata_status_irq);
+
/*
* Busy-wait for the drive status to be not "busy". Check then the status for
* all of the "good" bits and none of the "bad" bits, and if all is okay it
OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]);
}
+EXPORT_SYMBOL(ata_out_regfile);
+
/*
* Input a complete register file.
*/
rf->high_cylinder = IN_BYTE(ch->io_ports[IDE_HCYL_OFFSET]);
}
-
MODULE_LICENSE("GPL");
return 1;
}
- /*
- * Probe for a Gayle IDE interface (and optionally for an IDE doubler)
- */
+/*
+ * Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+ */
void __init gayle_init(void)
{
for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
ide_ioreg_t base, ctrlport, irqport;
- ide_ack_intr_t *ack_intr;
+ int (*ack_intr)(struct ata_channel *);
hw_regs_t hw;
int index;
unsigned long phys_base, res_start, res_n;
unsigned long read_timer(void)
{
+ extern spinlock_t i8253_lock;
unsigned long t, flags;
int i;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&i8253_lock, flags);
t = jiffies * 11932;
outb_p(0, 0x43);
i = inb_p(0x40);
i |= inb(0x40) << 8;
- restore_flags(flags);
+ spin_unlock_irqrestore(&i8253_lock, flags);
return(t - i);
}
#endif
NR_HD = 0;
return;
}
- request_region(HD_DATA, 8, "hd");
- request_region(HD_CMD, 1, "hd(cmd)");
+ if (!request_region(HD_DATA, 8, "hd")) {
+ printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+ NR_HD = 0;
+ free_irq(HD_IRQ, NULL);
+ return;
+ }
+ if (!request_region(HD_CMD, 1, "hd(cmd)")) {
+ printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+ NR_HD = 0;
+ free_irq(HD_IRQ, NULL);
+ release_region(HD_DATA, 8);
+ return;
+ }
hd_gendisk.nr_real = NR_HD;
if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
uptodate = 1;
- __ata_end_request(drive, rq, uptodate, 0);
+ ata_end_request(drive, rq, uptodate, 0);
}
if (dma) {
if (!dma_error) {
- __ata_end_request(drive, rq, 1, rq->nr_sectors);
+ ata_end_request(drive, rq, 1, rq->nr_sectors);
return ATA_OP_FINISHED;
} else
if (dma_error)
return ata_error(drive, rq, "dma error");
- __ata_end_request(drive, rq, 1, rq->nr_sectors);
+ ata_end_request(drive, rq, 1, rq->nr_sectors);
return ATA_OP_FINISHED;
}
If we get an error for the regular case, we assume
a CDI without additional audio tracks. In this case
the readable TOC is empty (CDI tracks are not included)
- and only holds the Leadout entry. Heiko Eißfeldt */
+ and only holds the Leadout entry. Heiko EiÃ^ßfeldt */
ntracks = 0;
stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
(char *)&toc->hdr,
}
/* Forwarding functions to generic routines. */
-static int ide_cdrom_ioctl (struct ata_device *drive,
+static int ide_cdrom_ioctl(struct ata_device *drive,
struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return cdrom_ioctl (inode, file, cmd, arg);
+ return cdrom_ioctl(inode, file, cmd, arg);
}
static int ide_cdrom_open (struct inode *ip, struct file *fp, struct ata_device *drive)
--rq->current_nr_sectors;
if (rq->current_nr_sectors <= 0) {
- if (!__ata_end_request(drive, rq, 1, 0)) {
+ if (!ata_end_request(drive, rq, 1, 0)) {
// printk("Request Ended stat: %02x\n", drive->status);
return ATA_OP_FINISHED;
if (!ata_status(drive, DRIVE_READY, drive->bad_wstat))
return ata_error(drive, rq, __FUNCTION__);
- if (!rq->current_nr_sectors && !__ata_end_request(drive, rq, 1, 0)) {
+ if (!rq->current_nr_sectors && !ata_end_request(drive, rq, 1, 0)) {
ret = ATA_OP_FINISHED;
} else {
if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) {
/* FIXME: this seems buggy */
if (rq->current_nr_sectors <= 0) {
- if (!__ata_end_request(drive, rq, 1, 0))
+ if (!ata_end_request(drive, rq, 1, 0))
return ATA_OP_FINISHED;
}
msect -= nsect;
return ata_error(drive, rq, __FUNCTION__);
}
if (!rq->nr_sectors) {
- __ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
+ ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
rq->bio = NULL;
ret = ATA_OP_FINISHED;
} else if (!ok) {
/* FIXME: this check doesn't make sense */
if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
- __ata_end_request(drive, rq, 0, 0);
+ ata_end_request(drive, rq, 0, 0);
return ATA_OP_FINISHED;
}
printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n", rq->buffer);
#endif
- ar->cmd = cmd;
- rq->special = ar;
+ ar->cmd = cmd;
+ rq->special = ar;
}
/* (ks/hs): Moved to start, do not use for multiple out commands.
return ATA_OP_CONTINUES;
}
- /* FIXME: Warning check for race between handler and prehandler
- * for writing first block of data. however since we are well
- * inside the boundaries of the seek, we should be okay.
- * FIXME: should be fixed --bzolnier
+ /* FIXME: Warning check for race between handlers for writing
+ * first block of data. However since we are well inside the
+ * boundaries of the seek, we should be okay.
*/
if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) {
ide_startstop_t ret;
*
* FIXME: Replace hard-coded 100, what about
* error handling?
+ *
+ * FIXME: Whatabout the IRE clearing and not clearing case?!
*/
for (i = 0; i < 100; ++i) {
- if (drive_is_ready(drive))
+ if (ata_status_irq(drive))
break;
}
- if (!drive_is_ready(drive)) {
+ if (!ata_status_irq(drive)) {
/* We are compleatly missing an error
* return path here.
* FIXME: We have only one? -alat
return ret;
}
-static int idedisk_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int idedisk_ioctl(struct ata_device *drive,
+ struct inode *inode, struct file *__fp,
+ unsigned int cmd, unsigned long arg)
{
struct hd_driveid *id = drive->id;
#include <linux/cdrom.h>
#include <linux/ide.h>
#include <linux/atapi.h>
+#include <linux/buffer_head.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
return 0;
if (!(rq->flags & REQ_SPECIAL)) {
- __ata_end_request(drive, rq, uptodate, 0);
+ ata_end_request(drive, rq, uptodate, 0);
return 0;
}
static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- ide_startstop_t startstop;
atapi_ireason_reg_t ireason;
int ret;
static void print_funcid (int func);
static int check_ide_device (unsigned long base);
-static void ide_interrupt_ack (void *dev);
+static int ide_interrupt_ack(struct ata_channel *);
static void m8xx_ide_tuneproc(struct ata_device *drive, byte pio);
typedef struct ide_ioport_desc {
/* register routine to tune PIO mode */
ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
- hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
+ hw->ack_intr = ide_interrupt_ack;
/* Enable Harddisk Interrupt,
* and make it edge sensitive
*/
ioport_dsc[data_port].reg_off[i],
i, base + ioport_dsc[data_port].reg_off[i]);
#endif
- *p++ = base + ioport_dsc[data_port].reg_off[i];
+ *p++ = base + ioport_dsc[data_port].reg_off[i];
}
if (irq) {
/* register routine to tune PIO mode */
ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
- hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
+ hw->ack_intr = ide_interrupt_ack;
/* Enable Harddisk Interrupt,
* and make it edge sensitive
*/
/* (11-18) Set edge detect for irq, no wakeup from low power mode */
((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
(0x80000000 >> ioport_dsc[data_port].irq);
-} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */
+} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */
-#endif /* CONFIG_IDE_8xx_DIRECT */
+#endif
/* -------------------------------------------------------------------- */
printk("%s[%d] %s: not implemented yet!\n",
__FILE__,__LINE__,__FUNCTION__);
-#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
+#endif
}
-static void
-ide_interrupt_ack (void *dev)
+static int ide_interrupt_ack(struct ata_channel *ch)
{
#ifdef CONFIG_IDE_8xx_PCCARD
u_int pscr, pipr;
/* clear the interrupt sources */
((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
-#else /* ! CONFIG_IDE_8xx_PCCARD */
+#else
/*
* Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
* MPC8xx's PCMCIA controller, so there is nothing to be done here
* for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
* The interrupt is handled somewhere else. -- Steven
*/
-#endif /* CONFIG_IDE_8xx_PCCARD */
-}
-
+#endif
+ return 0;
+}
/*
* CIS Tupel codes
q+= 2;
}
}
-#endif /* DEBUG_PCMCIA */
+#endif
switch (code) {
case CISTPL_VERS_1:
ident = p + 4;
return 0;
}
+#ifdef CONFIG_BLK_DEV_IDEDMA
+/*
+ * Setup DMA transfers on the channel.
+ */
+static void __init setup_channel_dma(struct pci_dev *dev,
+ struct ata_pci_device* d,
+ int autodma,
+ struct ata_channel *ch)
+{
+ unsigned long dma_base;
+
+ if (d->flags & ATA_F_NOADMA)
+ autodma = 0;
+
+ if (autodma)
+ ch->autodma = 1;
+
+ if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
+ return;
+
+ /*
+ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
+ */
+ dma_base = pci_resource_start(dev, 4);
+ if (dma_base) {
+ /* PDC20246, PDC20262, HPT343, & HPT366 */
+ if ((ch->unit == ATA_PRIMARY) && d->extra) {
+ request_region(dma_base + 16, d->extra, dev->name);
+ ch->dma_extra = d->extra;
+ }
+
+ /* If we are on the second channel, the dma base address will
+ * be one entry away from the primary interface.
+ */
+ if (ch->unit == ATA_SECONDARY)
+ dma_base += 8;
+
+ if (d->flags & ATA_F_SIMPLEX) {
+ outb(inb(dma_base + 2) & 0x60, dma_base + 2);
+ if (inb(dma_base + 2) & 0x80)
+ printk(KERN_INFO "%s: simplex device: DMA forced\n", dev->name);
+ } else {
+ /* If the device claims "simplex" DMA, this means only
+ * one of the two interfaces can be trusted with DMA at
+ * any point in time. So we should enable DMA only on
+ * one of the two interfaces.
+ */
+ if ((inb(dma_base + 2) & 0x80)) {
+ if ((!ch->drives[0].present && !ch->drives[1].present) ||
+ ch->unit == ATA_SECONDARY) {
+ printk(KERN_INFO "%s: simplex device: DMA disabled\n", dev->name);
+ dma_base = 0;
+ }
+ }
+ }
+ } else {
+ printk(KERN_INFO "%s: %s Bus-Master DMA was disabled by BIOS\n",
+ ch->name, dev->name);
+
+ return;
+ }
+
+ /* The function below will check itself whatever there is something to
+ * be done or not. We don't have therefore to care whatever it was
+ * already enabled by the primary channel run.
+ */
+ pci_set_master(dev);
+ if (d->init_dma)
+ d->init_dma(ch, dma_base);
+ else
+ ata_init_dma(ch, dma_base);
+}
+#endif
+
/*
* Setup a particular port on an ATA host controller.
*
int autodma)
{
unsigned long base = 0;
- unsigned long dma_base;
unsigned long ctl = 0;
ide_pci_enablebit_t *e = &(d->enablebits[port]);
struct ata_channel *ch;
if (ch->udma_four)
printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
+
#ifdef CONFIG_BLK_DEV_IDEDMA
/*
* Setup DMA transfers on the channel.
*/
- if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
- goto no_dma;
- /*
- * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
- */
- dma_base = pci_resource_start(dev, 4);
- if (dma_base) {
- /* PDC20246, PDC20262, HPT343, & HPT366 */
- if ((ch->unit == ATA_PRIMARY) && d->extra) {
- request_region(dma_base + 16, d->extra, dev->name);
- ch->dma_extra = d->extra;
- }
-
- /* If we are on the second channel, the dma base address will
- * be one entry away from the primary interface.
- */
- if (ch->unit == ATA_SECONDARY)
- dma_base += 8;
-
- if (d->flags & ATA_F_SIMPLEX) {
- outb(inb(dma_base + 2) & 0x60, dma_base + 2);
- if (inb(dma_base + 2) & 0x80)
- printk(KERN_INFO "%s: simplex device: DMA forced\n", dev->name);
- } else {
- /* If the device claims "simplex" DMA, this means only
- * one of the two interfaces can be trusted with DMA at
- * any point in time. So we should enable DMA only on
- * one of the two interfaces.
- */
- if ((inb(dma_base + 2) & 0x80)) {
- if ((!ch->drives[0].present && !ch->drives[1].present) ||
- ch->unit == ATA_SECONDARY) {
- printk(KERN_INFO "%s: simplex device: DMA disabled\n", dev->name);
- dma_base = 0;
- }
- }
- }
- } else {
- printk(KERN_INFO "%s: %s Bus-Master DMA was disabled by BIOS\n",
- ch->name, dev->name);
-
- goto no_dma;
- }
-
- /* The function below will check itself whatever there is something to
- * be done or not. We don't have therefore to care whatever it was
- * already enabled by the primary channel run.
- */
- pci_set_master(dev);
-
- if (autodma)
- ch->autodma = 1;
-
- if (d->init_dma)
- d->init_dma(ch, dma_base);
- else
- ata_init_dma(ch, dma_base);
+ setup_channel_dma(dev, d, autodma, ch);
#endif
-
no_dma:
/* Call chipset-specific routine for each enabled channel. */
if (d->init_channel)
#include <linux/completion.h>
#include <linux/ide.h>
#include <linux/atapi.h>
+#include <linux/buffer_head.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
* We do not support buffer cache originated requests.
*/
printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags);
- __ata_end_request(drive, rq, 0, 0); /* Let the common code handle it */
+ ata_end_request(drive, rq, 0, 0); /* Let the common code handle it */
return ATA_OP_FINISHED;
}
#include <asm/io.h>
#include <asm/bitops.h>
-#define DEBUG_TASKFILE 0 /* unset when fixed */
-
-#if DEBUG_TASKFILE
-#define DTF(x...) printk(##x)
-#else
-#define DTF(x...)
-#endif
-
/*
* Data transfer functions for polled IO.
*/
-
static void ata_read_32(struct ata_device *drive, void *buffer, unsigned int wcount)
{
insl(IDE_DATA_REG, buffer, wcount);
}
}
-/*
- * Needed for PCI irq sharing
- */
-int drive_is_ready(struct ata_device *drive)
-{
- if (test_bit(IDE_DMA, drive->channel->active))
- return udma_irq_status(drive);
-
- /*
- * Need to guarantee 400ns since last command was issued?
- */
-
- /* FIXME: promote this to the general status read method perhaps.
- */
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
- /*
- * We do a passive status test under shared PCI interrupts on
- * cards that truly share the ATA side interrupt, but may also share
- * an interrupt with another pci card/device. We make no assumptions
- * about possible isa-pnp and pci-pnp issues yet.
- */
- if (drive->channel->io_ports[IDE_CONTROL_OFFSET])
- drive->status = GET_ALTSTAT();
- else
-#endif
- ata_status(drive, 0, 0); /* Note: this may clear a pending IRQ! */
-
- if (drive->status & BUSY_STAT)
- return 0; /* drive busy: definitely not interrupting */
-
- return 1; /* drive ready: *might* be interrupting */
-}
-
-/*
- * This function issues a special IDE device request onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the request
- * queue, and the function sleeps until it has been processed. This is for use
- * when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of the request
- * queue, displacing the currently-being-processed request and this function
- * returns immediately without waiting for the new rq to be completed. This is
- * VERY DANGEROUS, and is intended for careful use by the ATAPI tape/cdrom
- * driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the request queue,
- * and the function returns immediately without waiting for the new rq to be
- * completed. This is again intended for careful use by the ATAPI tape/cdrom
- * driver code.
- */
-int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action)
-{
- unsigned long flags;
- struct ata_channel *ch = drive->channel;
- unsigned int major = ch->major;
- request_queue_t *q = &drive->queue;
- struct list_head *queue_head = &q->queue_head;
- DECLARE_COMPLETION(wait);
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (ch->chipset == ide_pdc4030 && rq->buffer)
- return -ENOSYS; /* special drive cmds not supported */
-#endif
- rq->errors = 0;
- rq->rq_status = RQ_ACTIVE;
- rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
- if (action == ide_wait)
- rq->waiting = &wait;
-
- spin_lock_irqsave(ch->lock, flags);
-
- if (action == ide_preempt)
- drive->rq = NULL;
- else if (!blk_queue_empty(&drive->queue))
- queue_head = queue_head->prev; /* ide_end and ide_wait */
-
- __elv_add_request(q, rq, queue_head);
-
- do_ide_request(q);
-
- spin_unlock_irqrestore(ch->lock, flags);
-
- if (action == ide_wait) {
- wait_for_completion(&wait); /* wait for it to be serviced */
- return rq->errors ? -EIO : 0; /* return -EIO if errors */
- }
-
- return 0;
-}
-
-
/*
* Invoked on completion of a special REQ_SPECIAL command.
*/
-static ide_startstop_t special_intr(struct ata_device *drive, struct
- request *rq) {
+static ide_startstop_t special_intr(struct ata_device *drive, struct request *rq) {
unsigned long flags;
struct ata_channel *ch =drive->channel;
struct ata_taskfile *ar = rq->special;
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar, char *buf)
{
- struct request req;
+ struct request *rq;
+ unsigned long flags;
+ struct ata_channel *ch = drive->channel;
+ request_queue_t *q = &drive->queue;
+ struct list_head *queue_head = &q->queue_head;
+ DECLARE_COMPLETION(wait);
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (ch->chipset == ide_pdc4030 && buf)
+ return -ENOSYS; /* special drive cmds not supported */
+#endif
+
+ rq = __blk_get_request(&drive->queue, READ);
+ if (!rq)
+ rq = __blk_get_request(&drive->queue, WRITE);
+
+ /*
+ * FIXME: Make sure there is a free slot on the list!
+ */
+
+ BUG_ON(!rq);
+
+ rq->flags = REQ_SPECIAL;
+ rq->buffer = buf;
+ rq->special = ar;
+ rq->errors = 0;
+ rq->rq_status = RQ_ACTIVE;
+ rq->waiting = &wait;
- ar->command_type = IDE_DRIVE_TASK_NO_DATA;
ar->XXX_handler = special_intr;
+ ar->command_type = IDE_DRIVE_TASK_NO_DATA;
+
+ spin_lock_irqsave(ch->lock, flags);
+
+ if (!blk_queue_empty(&drive->queue))
+ queue_head = queue_head->prev;
+ __elv_add_request(q, rq, queue_head);
+
+ q->request_fn(q);
+ spin_unlock_irqrestore(ch->lock, flags);
- memset(&req, 0, sizeof(req));
- req.flags = REQ_SPECIAL;
- req.buffer = buf;
- req.special = ar;
+ wait_for_completion(&wait); /* wait for it to be serviced */
- return ide_do_drive_cmd(drive, &req, ide_wait);
+ return rq->errors ? -EIO : 0; /* return -EIO if errors */
}
-EXPORT_SYMBOL(drive_is_ready);
-EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(ata_read);
EXPORT_SYMBOL(ata_write);
EXPORT_SYMBOL(ide_raw_taskfile);
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
-#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/blkpg.h>
return 0;
}
-int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
+int ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
{
unsigned long flags;
struct ata_channel *ch = drive->channel;
}
if (!end_that_request_first(rq, uptodate, nr_secs)) {
- add_blkdev_randomness(major(rq->rq_dev));
+ add_blkdev_randomness(ch->major);
if (!blk_rq_tagged(rq))
blkdev_dequeue_request(rq);
else
if (mode > XFER_UDMA_0)
mode--;
else
+
/*
- * OOPS we do not goto non Ultra DMA modes
- * without iCRC's available we force
- * the system to PIO and make the user
- * invoke the ATA-1 ATA-2 DMA modes.
+ * We do not do non Ultra DMA modes. Without iCRC's
+ * available, we force the system to PIO and make the
+ * user select the ATA-1 ATA-2 DMA modes himself.
*/
+
mode = XFER_PIO_4;
drive->channel->speedproc(drive, mode);
if (ata_ops(drive) && ata_ops(drive)->capacity)
return ata_ops(drive)->capacity(drive);
- /* This used to be 0x7fffffff, but since now we use the maximal drive
- * capacity value used by other kernel subsystems as well.
- */
-
return ~0UL;
}
-extern struct block_device_operations ide_fops[];
-
-static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
-
-/*
- * Poll the interface for completion every 50ms during an ATAPI drive reset
- * operation. If the drive has not yet responded, and we have not yet hit our
- * maximum waiting time, then the timer is restarted for another 50ms.
- */
-static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
-{
- struct ata_channel *ch = drive->channel;
- int ret = ATA_OP_FINISHED;
-
- ata_select(drive, 10);
- if (!ata_status(drive, 0, BUSY_STAT)) {
- if (time_before(jiffies, ch->poll_timeout)) {
- ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
- ret = ATA_OP_CONTINUES; /* continue polling */
- } else {
- ch->poll_timeout = 0; /* end of polling */
- printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status);
-
- ret = do_reset1(drive, 0); /* do it the old fashioned way */
- }
- } else {
- printk("%s: ATAPI reset complete\n", drive->name);
- ch->poll_timeout = 0; /* done polling */
-
- ret = ATA_OP_FINISHED;
- }
-
- return ret;
-}
-
-/*
- * Poll the interface for completion every 50ms during an ata reset operation.
- * If the drives have not yet responded, and we have not yet hit our maximum
- * waiting time, then the timer is restarted for another 50ms.
- */
-static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
-{
- struct ata_channel *ch = drive->channel;
- int ret;
-
- if (!ata_status(drive, 0, BUSY_STAT)) {
- if (time_before(jiffies, ch->poll_timeout)) {
- ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
- ret = ATA_OP_CONTINUES; /* continue polling */
- } else {
- ch->poll_timeout = 0; /* done polling */
- printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
- ++drive->failures;
- ret = ATA_OP_FINISHED;
- }
- } else {
- u8 stat;
-
- ch->poll_timeout = 0; /* done polling */
- printk("%s: reset: ", ch->name);
- if ((stat = GET_ERR()) == 1) {
- printk("success\n");
- drive->failures = 0;
- } else {
- const char *msg = "";
-
-#if FANCY_STATUS_DUMPS
- u8 val;
- static const char *messages[5] = {
- " passed",
- " formatter device",
- " sector buffer",
- " ECC circuitry",
- " controlling MPU error"
- };
-
- printk("master:");
- val = stat & 0x7f;
- if (val >= 1 && val <= 5)
- msg = messages[val -1];
- if (stat & 0x80)
- printk("; slave:");
-#endif
- printk(KERN_ERR "%s error [%02x]\n", msg, stat);
- ++drive->failures;
- }
-
- ret = ATA_OP_FINISHED;
- }
-
- return ret;
-}
-
-/*
- * Attempt to recover a confused drive by resetting it. Unfortunately,
- * resetting a disk drive actually resets all devices on the same interface, so
- * it can really be thought of as resetting the interface rather than resetting
- * the drive.
- *
- * ATAPI devices have their own reset mechanism which allows them to be
- * individually reset without clobbering other devices on the same interface.
- *
- * Unfortunately, the IDE interface does not generate an interrupt to let us
- * know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to
- * complete, (up to 30 seconds worst case). So, instead of busy-waiting here
- * for it, we set a timer to poll at 50ms intervals.
- */
-static ide_startstop_t do_reset1(struct ata_device *drive, int try_atapi)
-{
- unsigned int unit;
- unsigned long flags;
- struct ata_channel *ch = drive->channel;
-
- /* FIXME: --bzolnier */
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
-
- /* For an ATAPI device, first try an ATAPI SRST. */
- if (try_atapi) {
- if (drive->type != ATA_DISK) {
- check_crc_errors(drive);
- ata_select(drive, 20);
- OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
- ch->poll_timeout = jiffies + WAIT_WORSTCASE;
- ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
- __restore_flags(flags); /* local CPU only */
-
- return ATA_OP_CONTINUES;
- }
- }
-
- /*
- * First, reset any device state data we were maintaining
- * for any of the drives on this interface.
- */
- for (unit = 0; unit < MAX_DRIVES; ++unit)
- check_crc_errors(&ch->drives[unit]);
-
- __restore_flags(flags); /* local CPU only */
-
- return ATA_OP_CONTINUES;
-}
-
static inline u32 read_24(struct ata_device *drive)
{
return (IN_BYTE(IDE_HCYL_REG) << 16) |
return err;
}
-/*
- * This gets invoked in response to a drive unexpectedly having its DRQ_STAT
- * bit set. As an alternative to resetting the drive, it tries to clear the
- * condition by reading a sector's worth of data from the drive. Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-static void try_to_flush_leftover_data(struct ata_device *drive)
-{
- int i;
-
- if (drive->type != ATA_DISK)
- return;
-
- for (i = (drive->mult_count ? drive->mult_count : 1); i > 0; --i) {
- u32 buffer[SECTOR_WORDS];
-
- ata_read(drive, buffer, SECTOR_WORDS);
- }
-}
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-# define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
-#else
-# define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
-#endif
-
-/*
- * We are still on the old request path here so issuing the recalibrate command
- * directly should just work.
- */
-static int do_recalibrate(struct ata_device *drive)
-{
-
- if (drive->type != ATA_DISK)
- return ATA_OP_FINISHED;
-
- if (!IS_PDC4030_DRIVE) {
- struct ata_taskfile args;
-
- printk(KERN_INFO "%s: recalibrating...\n", drive->name);
- memset(&args, 0, sizeof(args));
- args.taskfile.sector_count = drive->sect;
- args.cmd = WIN_RESTORE;
- ide_raw_taskfile(drive, &args, NULL);
- printk(KERN_INFO "%s: done!\n", drive->name);
- }
-
- return IS_PDC4030_DRIVE ? ATA_OP_FINISHED : ATA_OP_CONTINUES;
-}
-
/*
* Take action based on the error returned by the drive.
+ *
+ * FIXME: Separate the error handling code out and call it only in cases where
+ * we really wan't to try to recover from the error and not just reporting.
*/
ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const char *msg)
{
err = ata_dump(drive, rq, msg);
- /* FIXME: at least !drive check is bogus --bzolnier */
- if (!drive || !rq)
- return ATA_OP_FINISHED;
-
- /* retry only "normal" I/O: */
- if (!(rq->flags & REQ_CMD)) {
+ /* Only try to recover from block I/O operations.
+ */
+ if (!rq || !(rq->flags & REQ_CMD)) {
rq->errors = 1;
return ATA_OP_FINISHED;
/* other bits are useless when BUSY */
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr))
- rq->errors |= ERROR_RESET; /* FIXME: What's that?! */
- else {
- if (drive->type == ATA_DISK && (stat & ERR_STAT)) {
- /* err has different meaning on cdrom and tape */
+ rq->errors |= ERROR_RESET;
+ else if (drive->type == ATA_DISK) {
+ /* The error bit has different meaning on cdrom and tape.
+ */
+ if (stat & ERR_STAT) {
if (err == ABRT_ERR) {
if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
return ATA_OP_FINISHED; /* some newer drives don't support WIN_SPECIFY */
drive->crc_count++; /* UDMA crc error -- just retry the operation */
else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
rq->errors = ERROR_MAX;
- else if (err & TRK0_ERR) /* help it find track zero */
- rq->errors |= ERROR_RECAL;
}
- /* pre bio (rq->cmd != WRITE) */
- if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
- try_to_flush_leftover_data(drive);
+
+ /* As an alternative to resetting the drive, we try to clear
+ * the condition by reading a sector's worth of data from the
+ * drive. Of course, this can not help if the drive is
+ * *waiting* for data from *us*.
+ */
+
+ if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) {
+ int i;
+
+ for (i = (drive->mult_count ? drive->mult_count : 1); i > 0; --i) {
+ u32 buffer[SECTOR_WORDS];
+
+ ata_read(drive, buffer, SECTOR_WORDS);
+ }
+ }
}
+ /* Force an abort if not even the status data is available. This will
+ * clear all pending IRQs on the drive as well.
+ */
if (!ata_status(drive, 0, BUSY_STAT | DRQ_STAT))
- OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); /* force an abort */
+ OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
+ /* Bail out immediately. */
if (rq->errors >= ERROR_MAX) {
printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name);
if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, rq, 0);
else
- __ata_end_request(drive, rq, 0, 0);
- } else {
- ++rq->errors;
- if ((rq->errors & ERROR_RESET) == ERROR_RESET)
- return do_reset1(drive, 1);
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- /* FIXME: tries to acquire the channel lock -Zwane */
- return do_recalibrate(drive);
- }
-
- return ATA_OP_FINISHED;
-}
-
-/*
- * This initiates handling of a new I/O request.
- */
-static ide_startstop_t start_request(struct ata_device *drive, struct request *rq)
-{
- struct ata_channel *ch = drive->channel;
- sector_t block;
- unsigned int minor = minor(rq->rq_dev);
- unsigned int unit = minor >> PARTN_BITS;
- ide_startstop_t ret;
-
- BUG_ON(!(rq->flags & REQ_STARTED));
-
-#ifdef DEBUG
- printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
-#endif
-
- /* bail early if we've exceeded max_failures */
- if (drive->max_failures && (drive->failures > drive->max_failures))
- goto kill_rq;
+ ata_end_request(drive, rq, 0, 0);
- if (unit >= MAX_DRIVES) {
- printk(KERN_ERR "%s: bad device number: %s\n", ch->name, kdevname(rq->rq_dev));
- goto kill_rq;
+ return ATA_OP_FINISHED;
}
- block = rq->sector;
+ ++rq->errors;
+ printk(KERN_INFO "%s: request error, nr. %d\n", drive->name, rq->errors);
- /* Strange disk manager remap.
+ /*
+ * Attempt to recover a confused drive by resetting it. Unfortunately,
+ * resetting a disk drive actually resets all devices on the same
+ * interface, so it can really be thought of as resetting the interface
+ * rather than resetting the drive.
+ *
+ * ATAPI devices have their own reset mechanism which allows them to be
+ * individually reset without clobbering other devices on the same
+ * interface.
+ *
+ * The IDE interface does not generate an interrupt to let us know when
+ * the reset operation has finished, so we must poll for this. This
+ * may take a very long time to complete.
+ *
+ * Maybe we can check if we are in IRQ context and schedule the CPU
+ * during this time. But for certain we should block all data transfers
+ * on the channel in question during those operations.
*/
- if (rq->flags & REQ_CMD)
- if (drive->type == ATA_DISK || drive->type == ATA_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 ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+ unsigned int unit;
+ struct ata_channel *ch = drive->channel;
+ int ret;
- ata_select(drive, 0);
- ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
- WAIT_READY, rq);
- if (ret != ATA_OP_READY) {
- printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
+ /* For an ATAPI device, first try an ATAPI SRST.
+ */
- goto kill_rq;
- }
+ if (drive->type != ATA_DISK) {
+ check_crc_errors(drive);
+ ata_select(drive, 20);
+ udelay(1);
+ ata_irq_enable(drive, 0);
+ OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
+ if (drive->quirk_list == 2)
+ ata_irq_enable(drive, 1);
+ udelay(1);
+ ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL);
+ ata_mask(drive);
+
+ if (ret == ATA_OP_READY) {
+ printk("%s: ATAPI reset complete\n", drive->name);
+
+ return ATA_OP_CONTINUES;
+ } else
+ printk(KERN_ERR "%s: ATAPI reset timed out, status=0x%02x\n",
+ drive->name, drive->status);
+ }
- if (!ata_ops(drive)) {
- printk(KERN_WARNING "%s: device type %d not supported\n",
- drive->name, drive->type);
- goto kill_rq;
- }
+ /* Reset all devices on channel.
+ */
- /* The normal way of execution is to pass and execute the request
- * handler down to the device type driver.
- */
+ /* First, reset any device state data we were maintaining for
+ * any of the drives on this interface.
+ */
+ for (unit = 0; unit < MAX_DRIVES; ++unit)
+ check_crc_errors(&ch->drives[unit]);
- if (ata_ops(drive)->do_request) {
- ret = ata_ops(drive)->do_request(drive, rq, block);
- } else {
- __ata_end_request(drive, rq, 0, 0);
- ret = ATA_OP_FINISHED;
- }
- return ret;
+ /* And now actually perform the reset operation.
+ */
+ printk("%s: ATA reset...\n", ch->name);
+ ata_select(drive, 20);
+ udelay(1);
+ ata_irq_enable(drive, 0);
-kill_rq:
- if (ata_ops(drive) && ata_ops(drive)->end_request)
- ata_ops(drive)->end_request(drive, rq, 0);
- else
- __ata_end_request(drive, rq, 0, 0);
+ /* This command actually looks suspicious, since I couldn't
+ * find it in any standard document.
+ */
+ OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]);
+ udelay(10);
+ OUT_BYTE(WIN_NOP, ch->io_ports[IDE_CONTROL_OFFSET]);
+ ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL);
+ ata_mask(drive);
+
+ if (ret == ATA_OP_READY)
+ printk("%s: ATA reset complete\n", drive->name);
+ else
+ printk(KERN_ERR "%s: ATA reset timed out, status=0x%02x\n",
+ drive->name, drive->status);
+ mdelay(100);
+ }
- return ATA_OP_FINISHED;
+ /* signal that we should retry this request */
+ return ATA_OP_CONTINUES;
}
/*
drive->sleep = timeout + jiffies;
}
-
/*
- * Determine the longest sleep time for the devices at this channel.
+ * Issue a new request.
+ * Caller must have already done spin_lock_irqsave(channel->lock, ...)
*/
-static unsigned long longest_sleep(struct ata_channel *channel)
+static void do_request(struct ata_channel *channel)
{
- unsigned long sleep = 0;
- int unit;
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- struct ata_device *drive = &channel->drives[unit];
-
- if (!drive->present)
- continue;
-
- /* This device is sleeping and waiting to be serviced
- * later than any other device we checked thus far.
- */
- if (drive->sleep && (!sleep || time_after(drive->sleep, sleep)))
- sleep = drive->sleep;
- }
+ struct ata_channel *ch;
+ struct ata_device *drive = NULL;
+ unsigned int unit;
+ ide_startstop_t ret;
- return sleep;
-}
+ __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
-/*
- * Select the next device which will be serviced. This selects only between
- * devices on the same channel, since everything else will be scheduled on the
- * queue level.
- */
-static struct ata_device *choose_urgent_device(struct ata_channel *channel)
-{
- struct ata_device *choice = NULL;
- unsigned long sleep = 0;
- int unit;
+ /*
+ * Select the next device which will be serviced. This selects
+ * only between devices on the same channel, since everything
+ * else will be scheduled on the queue level.
+ */
for (unit = 0; unit < MAX_DRIVES; ++unit) {
- struct ata_device *drive = &channel->drives[unit];
+ struct ata_device *tmp = &channel->drives[unit];
- if (!drive->present)
+ if (!tmp->present)
continue;
- /* There are no request pending for this device.
+ /* There are no requests pending for this device.
*/
- if (blk_queue_empty(&drive->queue))
+ if (blk_queue_empty(&tmp->queue))
continue;
+
/* This device still wants to remain idle.
*/
- if (drive->sleep && time_after(drive->sleep, jiffies))
+ if (tmp->sleep && time_after(tmp->sleep, jiffies))
continue;
- /* Take this device, if there is no device choosen thus far or
- * it's more urgent.
+ /* Take this device, if there is no device choosen thus
+ * far or which is more urgent.
*/
- if (!choice || (drive->sleep && (!choice->sleep || time_after(choice->sleep, drive->sleep)))) {
- if (!blk_queue_plugged(&drive->queue))
- choice = drive;
+ if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
+ if (!blk_queue_plugged(&tmp->queue))
+ drive = tmp;
}
}
- if (choice)
- return choice;
+ if (!drive) {
+ unsigned long sleep = 0;
- sleep = longest_sleep(channel);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ struct ata_device *tmp = &channel->drives[unit];
+
+ if (!tmp->present)
+ continue;
- if (sleep) {
+ /* This device is sleeping and waiting to be serviced
+ * earlier than any other device we checked thus far.
+ */
+ if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
+ sleep = tmp->sleep;
+ }
- /*
- * Take a short snooze, and then wake up again. Just in case
- * there are big differences in relative throughputs.. don't
- * want to hog the cpu too much.
- */
+ if (sleep) {
+ /*
+ * Take a short snooze, and then wake up again. Just
+ * in case there are big differences in relative
+ * throughputs.. don't want to hog the cpu too much.
+ */
- if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
- sleep = jiffies + WAIT_MIN_SLEEP;
+ if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
+ sleep = jiffies + WAIT_MIN_SLEEP;
#if 1
- if (timer_pending(&channel->timer))
- printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
+ if (timer_pending(&channel->timer))
+ printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
#endif
- set_bit(IDE_SLEEP, channel->active);
- mod_timer(&channel->timer, sleep);
- /* we purposely leave hwgroup busy while sleeping */
- } else {
- /* FIXME: use queue plugging instead of active to
- * block upper layers from stomping on us */
- /* Ugly, but how can we sleep for the lock otherwise? */
- ide_release_lock(&ide_irq_lock);/* for atari only */
- clear_bit(IDE_BUSY, channel->active);
- }
+ set_bit(IDE_SLEEP, channel->active);
+ mod_timer(&channel->timer, sleep);
- return NULL;
-}
+ /*
+ * We purposely leave us busy while sleeping becouse we
+ * are prepared to handle the IRQ from it.
+ *
+ * FIXME: Make sure sleeping can't interferre with
+ * operations of other devices on the same channel.
+ */
+ } else {
+ /* FIXME: use queue plugging instead of active to block
+ * upper layers from stomping on us */
+ /* Ugly, but how can we sleep for the lock otherwise?
+ * */
+
+ ide_release_lock(&ide_irq_lock);/* for atari only */
+ clear_bit(IDE_BUSY, channel->active);
+
+ /* All requests are done.
+ *
+ * Disable IRQs from the last drive on this channel, to
+ * make sure that it wan't throw stones at us when we
+ * are not prepared to take them.
+ */
-/*
- * Issue a new request.
- * Caller must have already done spin_lock_irqsave(channel->lock, ...)
- */
-static void do_request(struct ata_channel *channel)
-{
- ide_get_lock(&ide_irq_lock, ata_irq_request, channel);/* for atari only: POSSIBLY BROKEN HERE(?) */
- __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
+ if (channel->drive && !channel->drive->using_tcq)
+ ata_irq_enable(channel->drive, 0);
+ }
- while (!test_and_set_bit(IDE_BUSY, channel->active)) {
- struct ata_channel *ch;
- struct ata_device *drive;
- struct request *rq = NULL;
- ide_startstop_t startstop;
- int i;
+ return;
+ }
- /* this will clear IDE_BUSY, if appropriate */
- drive = choose_urgent_device(channel);
+ /* Remember the last drive we where acting on.
+ */
+ ch = drive->channel;
+ ch->drive = drive;
- if (!drive)
- break;
+ /* Feed commands to a drive until it barfs.
+ */
+ do {
+ struct request *rq = NULL;
+ sector_t block;
- /* Remember the last drive we where acting on.
+ /* Abort early if we can't queue another command. for non tcq,
+ * ata_can_queue is always 1 since we never get here unless the
+ * drive is idle.
*/
- ch = drive->channel;
- ch->drive = drive;
- /* Make sure that all drives on channels sharing the IRQ line
- * with us won't generate IRQ's during our activity.
- */
- for (i = 0; i < MAX_HWIFS; ++i) {
- struct ata_channel *tmp = &ide_hwifs[i];
- int j;
+ if (!ata_can_queue(drive)) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
+ }
+ break;
+ }
- if (!tmp->present)
- continue;
+ drive->sleep = 0;
- if (ch->lock != tmp->lock)
- continue;
+ if (test_bit(IDE_DMA, ch->active)) {
+ printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
+ break;
+ }
- /* Only care if there is any drive on the channel in
- * question.
- */
- for (j = 0; j < MAX_DRIVES; ++j) {
- struct ata_device * other = &tmp->drives[j];
+ /* There's a small window between where the queue could be
+ * replugged while we are in here when using tcq (in which case
+ * the queue is probably empty anyways...), so check and leave
+ * if appropriate. When not using tcq, this is still a severe
+ * BUG!
+ */
+
+ if (blk_queue_plugged(&drive->queue)) {
+ BUG_ON(!drive->using_tcq);
+ break;
+ }
- if (other->present)
- ata_irq_enable(other, 0);
+ if (!(rq = elv_next_request(&drive->queue))) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
}
+ drive->rq = NULL;
+
+ break;
}
+ /* If there are queued commands, we can't start a
+ * non-fs request (really, a non-queuable command)
+ * until the queue is empty.
+ */
+ if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
+ break;
+
+ drive->rq = rq;
+
+ spin_unlock(ch->lock);
+ ide__sti(); /* allow other IRQs while we start this request */
+
/*
- * Feed commands to a drive until it barfs.
+ * This initiates handling of a new I/O request.
*/
- do {
- if (!test_bit(IDE_BUSY, ch->active))
- printk(KERN_ERR "%s: error: not busy while queueing!\n", drive->name);
- /* Abort early if we can't queue another command. for
- * non tcq, ata_can_queue is always 1 since we never
- * get here unless the drive is idle.
- */
- if (!ata_can_queue(drive)) {
- if (!ata_pending_commands(drive))
- clear_bit(IDE_BUSY, ch->active);
- break;
- }
+ BUG_ON(!(rq->flags & REQ_STARTED));
- drive->sleep = 0;
+#ifdef DEBUG
+ printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
+#endif
- if (test_bit(IDE_DMA, ch->active)) {
- printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
- break;
- }
+ /* bail early if we've exceeded max_failures */
+ if (drive->max_failures && (drive->failures > drive->max_failures))
+ goto kill_rq;
- /* There's a small window between where the queue could
- * be replugged while we are in here when using tcq (in
- * which case the queue is probably empty anyways...),
- * so check and leave if appropriate. When not using
- * tcq, this is still a severe BUG!
- */
- if (blk_queue_plugged(&drive->queue)) {
- BUG_ON(!drive->using_tcq);
- break;
- }
+ block = rq->sector;
- if (!(rq = elv_next_request(&drive->queue))) {
- if (!ata_pending_commands(drive))
- clear_bit(IDE_BUSY, ch->active);
- drive->rq = NULL;
- break;
- }
+ /* Strange disk manager remap.
+ */
+ if (rq->flags & REQ_CMD)
+ if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
+ block += drive->sect0;
- /* If there are queued commands, we can't start a
- * non-fs request (really, a non-queuable command)
- * until the queue is empty.
- */
- if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
- break;
+ /* 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 */
+
+ ata_select(drive, 0);
+ ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
+ WAIT_READY, rq);
+
+ if (ret != ATA_OP_READY) {
+ printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
+
+ goto kill_rq;
+ }
+
+ if (!ata_ops(drive)) {
+ printk(KERN_WARNING "%s: device type %d not supported\n",
+ drive->name, drive->type);
+ goto kill_rq;
+ }
- drive->rq = rq;
+ /* The normal way of execution is to pass and execute the request
+ * handler down to the device type driver.
+ */
+
+ if (ata_ops(drive)->do_request) {
+ ret = ata_ops(drive)->do_request(drive, rq, block);
+ } else {
+kill_rq:
+ if (ata_ops(drive) && ata_ops(drive)->end_request)
+ ata_ops(drive)->end_request(drive, rq, 0);
+ else
+ ata_end_request(drive, rq, 0, 0);
+ ret = ATA_OP_FINISHED;
- spin_unlock(ch->lock);
- ide__sti(); /* allow other IRQs while we start this request */
- startstop = start_request(drive, rq);
- spin_lock_irq(ch->lock);
+ }
+ spin_lock_irq(ch->lock);
- /* command started, we are busy */
- } while (startstop != ATA_OP_CONTINUES);
- /* make sure the BUSY bit is set */
- /* FIXME: perhaps there is some place where we miss to set it? */
+ /* continue if command started, so we are busy */
+ } while (ret != ATA_OP_CONTINUES);
+ /* make sure the BUSY bit is set */
+ /* FIXME: perhaps there is some place where we miss to set it? */
// set_bit(IDE_BUSY, ch->active);
- }
}
void do_ide_request(request_queue_t *q)
{
- do_request(q->queuedata);
+ struct ata_channel *ch = q->queuedata;
+
+ while (!test_and_set_bit(IDE_BUSY, ch->active)) {
+ do_request(ch);
+ }
}
/*
* also be invoked as a result of a "sleep" operation triggered by the
* mod_timer() call in do_request.
*
- * FIXME: this should take a drive context instead of a channel.
+ * FIXME: This should take a drive context instead of a channel.
+ * FIXME: This should not explicitly reenter the request handling engine.
*/
void ide_timer_expiry(unsigned long data)
{
* as timer expired), or we were "sleeping" to give other
* devices a chance. Either way, we don't really want to
* complain about anything.
+ *
+ * FIXME: Do we really still have to clear IDE_BUSY here?
*/
if (test_and_clear_bit(IDE_SLEEP, ch->active))
__cli(); /* local CPU only, as if we were handling an interrupt */
if (ch->poll_timeout) {
ret = handler(drive, drive->rq);
- } else if (drive_is_ready(drive)) {
+ } else if (ata_status_irq(drive)) {
if (test_bit(IDE_DMA, ch->active))
udma_irq_lost(drive);
(void) ide_ack_intr(ch);
enable_irq(ch->irq);
spin_lock_irq(ch->lock);
- if (ret == ATA_OP_FINISHED)
- clear_bit(IDE_BUSY, ch->active);
-
- /* Reenter the request handling engine */
- do_request(ch);
+ if (ret == ATA_OP_FINISHED) {
+ /* Reenter the request handling engine. */
+ do_request(ch);
+ }
}
spin_unlock_irqrestore(ch->lock, flags);
}
*/
static void unexpected_irq(int irq)
{
+ /* Try to not flood the console with msgs */
+ static unsigned long last_msgtime; /* = 0 */
+ static int count; /* = 0 */
int i;
for (i = 0; i < MAX_HWIFS; ++i) {
struct ata_channel *ch = &ide_hwifs[i];
+ int j;
struct ata_device *drive;
- if (!ch->present)
+ if (!ch->present || ch->irq != irq)
continue;
- if (ch->irq != irq)
- continue;
+ for (j = 0; j < MAX_DRIVES; ++j) {
+ drive = &ch->drives[j];
- /* FIXME: this is a bit weak */
- drive = &ch->drives[0];
-
- if (!ata_status(drive, READY_STAT, BAD_STAT)) {
- /* Try to not flood the console with msgs */
- static unsigned long last_msgtime;
- static int count;
+ /* this drive is idle */
+ if (ata_status(drive, READY_STAT, BAD_STAT))
+ continue;
++count;
- if (time_after(jiffies, last_msgtime + HZ)) {
- last_msgtime = jiffies;
- printk("%s: unexpected interrupt, status=0x%02x, count=%d\n",
- ch->name, drive->status, count);
- }
+
+ /* don't report too frequently */
+ if (!time_after(jiffies, last_msgtime + HZ))
+ continue;
+
+ last_msgtime = jiffies;
+ printk("%s: unexpected interrupt, status=0x%02x, count=%d\n",
+ ch->name, drive->status, count);
}
}
}
unsigned long flags;
struct ata_device *drive;
ata_handler_t *handler;
- ide_startstop_t startstop;
+ ide_startstop_t ret;
spin_lock_irqsave(ch->lock, flags);
goto out_lock;
handler = ch->handler;
- if (handler == NULL || ch->poll_timeout != 0) {
+ drive = ch->drive;
+ if (!handler || ch->poll_timeout) {
#if 0
printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq);
#endif
+
/*
- * Not expecting an interrupt from this drive.
- * That means this could be:
- * (1) an interrupt from another PCI device
- * sharing the same PCI INT# as us.
- * or (2) a drive just entered sleep or standby mode,
- * and is interrupting to let us know.
- * or (3) a spurious interrupt of unknown origin.
+ * Not expecting an interrupt from this drive. That means this
+ * could be:
+ *
+ * - an interrupt from another PCI device sharing the same PCI
+ * INT# as us.
*
- * For PCI, we cannot tell the difference,
- * so in that case we just ignore it and hope it goes away.
+ * - a drive just entered sleep or standby mode, and is
+ * interrupting to let us know.
+ *
+ * - a spurious interrupt of unknown origin.
+ *
+ * For PCI, we cannot tell the difference, so in that case we
+ * just clear it and hope it goes away.
*/
+
#ifdef CONFIG_PCI
if (ch->pci_dev && !ch->pci_dev->vendor)
#endif
- {
- /* Probably not a shared PCI interrupt, so we can
- * safely try to do something about it:
- */
unexpected_irq(irq);
#ifdef CONFIG_PCI
- } else {
- /*
- * Whack the status register, just in case we have a leftover pending IRQ.
- */
- IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]);
+ else
+ ata_status(drive, READY_STAT, BAD_STAT);
#endif
- }
+
goto out_lock;
}
- drive = ch->drive;
- if (!drive_is_ready(drive)) {
- /*
- * This happens regularly when we share a PCI IRQ with another device.
+ if (!ata_status_irq(drive)) {
+ /* This happens regularly when we share a PCI IRQ with another device.
* Unfortunately, it can also happen with some buggy drives that trigger
* the IRQ before their status register is up to date. Hopefully we have
* enough advance overhead that the latter isn't a problem.
*/
+
goto out_lock;
}
+
/* paranoia */
if (!test_and_set_bit(IDE_BUSY, ch->active))
- printk(KERN_ERR "%s: %s: hwgroup was not busy!?\n", drive->name, __FUNCTION__);
+ printk(KERN_ERR "%s: %s: channel was not busy!?\n", drive->name, __FUNCTION__);
+
ch->handler = NULL;
del_timer(&ch->timer);
if (ch->unmask)
ide__sti();
- /* service this interrupt, may set handler for next interrupt */
- startstop = handler(drive, drive->rq);
+ /*
+ * Service this interrupt, this may setup handler for next interrupt.
+ */
+ ret = handler(drive, drive->rq);
spin_lock_irq(ch->lock);
/*
- * Note that handler() may have set things up for another
- * interrupt to occur soon, but it cannot happen until
- * we exit from this routine, because it will be the
- * same irq as is currently being serviced here, and Linux
- * won't allow another of the same (on any CPU) until we return.
+ * Note that handler() may have set things up for another interrupt to
+ * occur soon, but it cannot happen until we exit from this routine,
+ * because it will be the same irq as is currently being serviced here,
+ * and Linux won't allow another of the same (on any CPU) until we
+ * return.
*/
- if (startstop == ATA_OP_FINISHED) {
- if (!ch->handler) { /* paranoia */
- clear_bit(IDE_BUSY, ch->active);
+
+ if (ret == ATA_OP_FINISHED) {
+
+ /* Reenter the request handling engine if we are not expecting
+ * another interrupt.
+ */
+
+ if (!ch->handler)
do_request(ch);
- } else {
- printk("%s: %s: huh? expected NULL handler on exit\n", drive->name, __FUNCTION__);
- }
+ else
+ printk("%s: %s: huh? expected NULL handler on exit\n",
+ drive->name, __FUNCTION__);
}
out_lock:
*/
#ifdef CONFIG_KMOD
- if (drive->driver == NULL) {
+ if (!drive->driver) {
char *module = NULL;
switch (drive->type) {
drive->usage--;
if (ata_ops(drive) && ata_ops(drive)->release)
ata_ops(drive)->release(inode, file, drive);
+
return 0;
}
EXPORT_SYMBOL(ata_dump);
EXPORT_SYMBOL(ata_error);
-EXPORT_SYMBOL(__ata_end_request);
+EXPORT_SYMBOL(ata_end_request);
EXPORT_SYMBOL(ide_stall_queue);
EXPORT_SYMBOL(ide_setup_ports);
* Setup hw_regs_t structure described by parameters. You may set up the hw
* structure yourself OR use this routine to do it for you.
*/
-void ide_setup_ports(hw_regs_t *hw,
- ide_ioreg_t base,
- int *offsets,
- ide_ioreg_t ctrl,
- ide_ioreg_t intr,
- ide_ack_intr_t *ack_intr,
+void ide_setup_ports(hw_regs_t *hw, ide_ioreg_t base, int *offsets,
+ ide_ioreg_t ctrl, ide_ioreg_t intr,
+ int (*ack_intr)(struct ata_channel *),
int irq)
{
int i;
* FIXME: rewrite the following crap:
*/
-/*
- * stridx() returns the offset of c within s,
- * or -1 if c is '\0' or not found within s.
- */
-static int __init stridx (const char *s, char c)
-{
- char *i = strchr(s, c);
-
- return (i && c) ? i - s : -1;
-}
-
/*
* Parsing for ide_setup():
*
* 3. if the remainder is a series of no more than max_vals numbers
* separated by commas, the numbers are saved in vals[] and a
* count of how many were saved is returned. Base10 is assumed,
- * and base16 is allowed when prefixed with "0x".
+ * and base16 is allowed when prefixed with "0x". The number of
+ * values read will be placed in vals[0], and the values read will
+ * placed in vals[1] to vals[max_vals].
* 4. otherwise, zero is returned.
*/
static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
{
- static const char decimal[] = "0123456789";
- static const char hex[] = "0123456789abcdef";
- int i, n;
+ int i;
if (*s++ == '=') {
/*
* or base16 when prefixed with "0x".
* Return a count of how many were found.
*/
- for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
- vals[n] = i;
- while ((i = stridx(decimal, *++s)) >= 0)
- vals[n] = (vals[n] * 10) + i;
- if (*s == 'x' && !vals[n]) {
- while ((i = stridx(hex, *++s)) >= 0)
- vals[n] = (vals[n] * 0x10) + i;
- }
- if (++n == max_vals)
- break;
- if (*s == ',' || *s == ';')
- ++s;
- }
- if (!*s)
- return n;
+ get_options(s, max_vals+1, vals);
+ return vals[0];
}
- return 0; /* zero = nothing matched */
+ return 0;
}
/*
*/
int __init ide_setup(char *s)
{
- int i, vals[3];
+ int i, vals[4];
struct ata_channel *ch;
struct ata_device *drive;
unsigned int hw, unit;
return 0;
if (strncmp(s,"ide",3) &&
- strncmp(s,"idebus",6) &&
strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
unit = unit % MAX_DRIVES;
ch = &ide_hwifs[hw];
drive = &ch->drives[unit];
- if (!strncmp(s + 4, "ide-", 4)) {
+ if (!strncmp(s+3, "=ide-", 5)) {
strncpy(drive->driver_req, s + 4, 9);
goto done;
}
/*
* Look for last lun option: "hdxlun="
*/
- if (!strncmp(&s[3], "lun", 3)) {
- if (match_parm(&s[6], NULL, vals, 1) != 1)
+ if (!strncmp(s+3, "lun=", 4)) {
+ if (*get_options(s+7, 2, vals) || vals[0]!=1)
goto bad_option;
- if (vals[0] >= 0 && vals[0] <= 7) {
- drive->last_lun = vals[0];
+ if (vals[1] >= 0 && vals[1] <= 7) {
+ drive->last_lun = vals[1];
drive->forced_lun = 1;
} else
printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done;
}
- switch (match_parm(&s[3], hd_words, vals, 3)) {
+ switch (match_parm(s+3, hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */
#endif
case 3: /* cyl,head,sect */
drive->type = ATA_DISK;
- drive->cyl = drive->bios_cyl = vals[0];
- drive->head = drive->bios_head = vals[1];
- drive->sect = drive->bios_sect = vals[2];
+ drive->cyl = drive->bios_cyl = vals[1];
+ drive->head = drive->bios_head = vals[2];
+ drive->sect = drive->bios_sect = vals[3];
drive->present = 1;
drive->forced_geom = 1;
ch->noprobe = 0;
/*
* Look for bus speed option: "idebus="
*/
- if (!strncmp(s, "idebus", 6)) {
- if (match_parm(&s[6], NULL, vals, 1) != 1)
+ if (!strncmp(s, "idebus=", 7)) {
+ if (*get_options(s+7, 2, vals) || vals[0] != 1)
goto bad_option;
- idebus_parameter = vals[0];
+ idebus_parameter = vals[1];
goto done;
}
if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
- * -8,-9,-10. -11 : are reserved for future idex calls to ease the hardcoding.
*/
+ const char *ide_options[] = {
+ "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL };
const char *ide_words[] = {
- "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
- "minus8", "minus9", "minus10", "minus11",
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0';
ch = &ide_hwifs[hw];
+
+ switch (match_parm(s+4, ide_options, vals, 1)) {
+ case -7: /* ata66 */
+#ifdef CONFIG_PCI
+ ch->udma_four = 1;
+ goto done;
+#else
+ ch->udma_four = 0;
+ goto bad_channel;
+#endif
+ case -6: /* dma */
+ ch->autodma = 1;
+ goto done;
+ case -5: /* reset */
+ ch->reset = 1;
+ goto done;
+ case -4: /* noautotune */
+ ch->drives[0].autotune = 2;
+ ch->drives[1].autotune = 2;
+ goto done;
+ case -3: /* autotune */
+ ch->drives[0].autotune = 1;
+ ch->drives[1].autotune = 1;
+ goto done;
+ case -2: /* "serialize" */
+ do_serialize:
+ {
+ struct ata_channel *mate;
+
+ mate = &ide_hwifs[hw ^ 1];
+ ch->serialized = 1;
+ mate->serialized = 1;
+ }
+ goto done;
+
+ case -1: /* "noprobe" */
+ ch->noprobe = 1;
+ goto done;
+ }
+
i = match_parm(&s[4], ide_words, vals, 3);
/*
* Cryptic check to ensure chipset not already set for a channel:
*/
- if (i > 0 || i <= -11) { /* is parameter a chipset name? */
- if (ch->chipset != ide_unknown)
+ if (i) { /* is parameter a chipset name? */
+ if (ide_hwifs[hw].chipset != ide_unknown)
goto bad_option; /* chipset already specified */
- if (i <= -11 && i != -18 && hw != 0)
+ if (i != -7 && hw != 0)
goto bad_channel; /* chipset drivers are for "ide0=" only */
- if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
+ if (i != -7 && ide_hwifs[1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
switch (i) {
#ifdef CONFIG_BLK_DEV_PDC4030
- case -18: /* "dc4030" */
+ case -7: /* "dc4030" */
{
extern void init_pdc4030(void);
init_pdc4030();
}
#endif
#ifdef CONFIG_BLK_DEV_ALI14XX
- case -17: /* "ali14xx" */
+ case -6: /* "ali14xx" */
{
extern void init_ali14xx (void);
init_ali14xx();
}
#endif
#ifdef CONFIG_BLK_DEV_UMC8672
- case -16: /* "umc8672" */
+ case -5: /* "umc8672" */
{
extern void init_umc8672 (void);
init_umc8672();
}
#endif
#ifdef CONFIG_BLK_DEV_DTC2278
- case -15: /* "dtc2278" */
+ case -4: /* "dtc2278" */
{
extern void init_dtc2278 (void);
init_dtc2278();
}
#endif
#ifdef CONFIG_BLK_DEV_CMD640
- case -14: /* "cmd640_vlb" */
+ case -3: /* "cmd640_vlb" */
{
extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
}
#endif
#ifdef CONFIG_BLK_DEV_HT6560B
- case -13: /* "ht6560b" */
+ case -2: /* "ht6560b" */
{
extern void init_ht6560b (void);
init_ht6560b();
}
#endif
#if CONFIG_BLK_DEV_QD65XX
- case -12: /* "qd65xx" */
+ case -1: /* "qd65xx" */
{
extern void init_qd65xx (void);
init_qd65xx();
goto done;
}
#endif
- case -11: /* minus11 */
- case -10: /* minus10 */
- case -9: /* minus9 */
- case -8: /* minus8 */
- goto bad_option;
- case -7: /* ata66 */
-#ifdef CONFIG_PCI
- ch->udma_four = 1;
- goto done;
-#else
- ch->udma_four = 0;
- goto bad_channel;
-#endif
- case -6: /* dma */
- ch->autodma = 1;
- goto done;
- case -5: /* reset */
- ch->reset = 1;
- goto done;
- case -4: /* noautotune */
- ch->drives[0].autotune = 2;
- ch->drives[1].autotune = 2;
- goto done;
- case -3: /* autotune */
- ch->drives[0].autotune = 1;
- ch->drives[1].autotune = 1;
- goto done;
- case -2: /* "serialize" */
- do_serialize:
- {
- struct ata_channel *mate;
-
- mate = &ide_hwifs[hw ^ 1];
- ch->serialized = 1;
- mate->serialized = 1;
- }
- goto done;
-
- case -1: /* "noprobe" */
- ch->noprobe = 1;
- goto done;
-
case 1: /* base */
- vals[1] = vals[0] + 0x206; /* default ctl */
+ vals[2] = vals[1] + 0x206; /* default ctl */
case 2: /* base,ctl */
- vals[2] = 0; /* default irq = probe for it */
+ vals[3] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
- ch->hw.irq = vals[2];
- ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &ch->irq);
+ ch->hw.irq = vals[3];
+ ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[1], (ide_ioreg_t) vals[2], &ch->irq);
memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
- ch->irq = vals[2];
+ ch->irq = vals[3];
ch->noprobe = 0;
ch->chipset = ide_generic;
goto done;
if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
if (!dma_stat) {
- __ata_end_request(drive, rq, 1, rq->nr_sectors);
+ ata_end_request(drive, rq, 1, rq->nr_sectors);
return ATA_OP_FINISHED;
}
void udma_pci_timeout(struct ata_device *drive)
{
- printk(KERN_ERR "ATA: UDMA timeout occured %s!\n", drive->name);
+ printk(KERN_ERR "%s: UDMA timeout!\n", drive->name);
}
void udma_pci_irq_lost(struct ata_device *drive)
* linux/drivers/ide/pdc202xx.c Version 0.30 May. 28, 2002
*
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2002 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2002 BartÅ^Âomiej Å»oÅ^Ânierkiewicz
*
- * Portions Copyright (C) 1999 Promise Technology, Inc.
- * Author: Frank Tiernan (frankt@promise.com)
+ * Portions Copyright (C) 1999-2002 Promise Technology, Inc.
+ * Author: Frank Tiernan <frankt@promise.com>
+ * Hank Yang <support@promise.com.tw>
*
* May be copied or modified under the terms of the GNU General Public License
*
*
* The latest chipset code will support the following ::
* Three Ultra33 controllers and 12 drives.
+ *
* 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word.
* The 8/4 ratio is a BIOS code limit by promise.
*
* UNLESS you enable "CONFIG_PDC202XX_BURST"
*
+ * History:
+ * Sync 2.5 driver with Promise 2.4 driver v1.20.0.7 (07/11/02):
+ * - Add PDC20271 support
+ * - Disable LBA48 support on PDC20262
+ * - Fix ATAPI UDMA port value
+ * - Add new quirk drive
+ * - Adjust timings for all drives when using ATA133
+ * - Update pdc202xx_reset() waiting time
+ *
*/
#include <linux/config.h>
}
#endif /* PDC202XX_DECODE_REGISTER_INFO */
+static struct ata_device* drives[4];
+
int check_in_drive_lists(struct ata_device *drive)
{
static const char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLP KA6.4",
"QUANTUM FIREBALLP KA9.1",
"QUANTUM FIREBALLP LM20.4",
+ "QUANTUM FIREBALLP KX13.6",
"QUANTUM FIREBALLP KX20.5",
"QUANTUM FIREBALLP KX27.3",
"QUANTUM FIREBALLP LM20.5",
NULL
};
- const char**list = pdc_quirk_drives;
+
+ const char**list = pdc_quirk_drives;
struct hd_driveid *id = drive->id;
while (*list)
switch(ch->pci_dev->device) {
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20275:
+ case PCI_DEVICE_ID_PROMISE_20271:
case PCI_DEVICE_ID_PROMISE_20269:
map |= XFER_UDMA_133;
case PCI_DEVICE_ID_PROMISE_20268R:
static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
{
struct ata_channel *hwif = drive->channel;
-#ifdef CONFIG_BLK_DEV_IDEDMA
- unsigned long indexreg = (hwif->dma_base + 1);
- unsigned long datareg = (hwif->dma_base + 3);
-#else
u32 high_16 = pci_resource_start(hwif->pci_dev, 4);
- unsigned long indexreg = high_16 + (hwif->unit ? 0x09 : 0x01);
- unsigned long datareg = (indexreg + 2);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- byte thold = 0x10;
- byte adj = (drive->dn%2) ? 0x08 : 0x00;
+ u32 indexreg = high_16 + (hwif->unit ? 0x09 : 0x01);
+ u32 datareg = indexreg + 2;
+
+ u8 adj = (drive->dn % 2) ? 0x08 : 0x00;
+ u8 thold = 0x10;
+ int err, i, j = hwif->unit ? 2 : 0;
#ifdef CONFIG_BLK_DEV_IDEDMA
+ /* Setting tHOLD bit to 0 if using UDMA mode 2 */
if (speed == XFER_UDMA_2) {
OUT_BYTE((thold + adj), indexreg);
OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg);
}
- switch (speed) {
- case XFER_UDMA_7:
- speed = XFER_UDMA_6;
- case XFER_UDMA_6:
- set_2regs(0x10, 0x1a);
- set_2regs(0x11, 0x01);
- set_2regs(0x12, 0xcb);
- break;
- case XFER_UDMA_5:
- set_2regs(0x10, 0x1a);
- set_2regs(0x11, 0x02);
- set_2regs(0x12, 0xcb);
- break;
- case XFER_UDMA_4:
- set_2regs(0x10, 0x1a);
- set_2regs(0x11, 0x03);
- set_2regs(0x12, 0xcd);
- break;
- case XFER_UDMA_3:
- set_2regs(0x10, 0x1a);
- set_2regs(0x11, 0x05);
- set_2regs(0x12, 0xcd);
- break;
- case XFER_UDMA_2:
- set_2regs(0x10, 0x2a);
- set_2regs(0x11, 0x07);
- set_2regs(0x12, 0xcd);
- break;
- case XFER_UDMA_1:
- set_2regs(0x10, 0x3a);
- set_2regs(0x11, 0x0a);
- set_2regs(0x12, 0xd0);
- break;
- case XFER_UDMA_0:
- set_2regs(0x10, 0x4a);
- set_2regs(0x11, 0x0f);
- set_2regs(0x12, 0xd5);
- break;
- case XFER_MW_DMA_2:
- set_2regs(0x0e, 0x69);
- set_2regs(0x0f, 0x25);
- break;
- case XFER_MW_DMA_1:
- set_2regs(0x0e, 0x6b);
- set_2regs(0x0f, 0x27);
- break;
- case XFER_MW_DMA_0:
- set_2regs(0x0e, 0xdf);
- set_2regs(0x0f, 0x5f);
- break;
-#else
- switch (speed) {
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- case XFER_PIO_4:
- set_2regs(0x0c, 0x23);
- set_2regs(0x0d, 0x09);
- set_2regs(0x13, 0x25);
- break;
- case XFER_PIO_3:
- set_2regs(0x0c, 0x27);
- set_2regs(0x0d, 0x0d);
- set_2regs(0x13, 0x35);
- break;
- case XFER_PIO_2:
- set_2regs(0x0c, 0x23);
- set_2regs(0x0d, 0x26);
- set_2regs(0x13, 0x64);
- break;
- case XFER_PIO_1:
- set_2regs(0x0c, 0x46);
- set_2regs(0x0d, 0x29);
- set_2regs(0x13, 0xa4);
- break;
- case XFER_PIO_0:
- set_2regs(0x0c, 0xfb);
- set_2regs(0x0d, 0x2b);
- set_2regs(0x13, 0xac);
- break;
- default:
- ;
+#endif
+
+ for (i = 0 ; i < 2 ; i++)
+ if (hwif->drives[i].present)
+ drives[i+j] = &hwif->drives[i];
+
+ err = ide_config_drive_speed(drive, speed);
+
+ /* For modes < UDMA mode 6 we need only to SET_FEATURE */
+ if (speed < XFER_UDMA_6)
+ return err;
+
+ /* We need to adjust timings to ATA133 clock if ATA133 drives exist */
+ for (i = 0 ; i < 4 ; i++) {
+ if (!drives[i])
+ continue;
+
+ /* Primary = 0x01, Secondary = 0x09 */
+ indexreg = high_16 + ((i > 1) ? 0x09 : 0x01);
+ datareg = indexreg + 2;
+
+ /* Master = 0x00, Slave = 0x08 */
+ adj = (i % 2) ? 0x08 : 0x00;
+
+ switch (drives[i]->current_speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ case XFER_UDMA_6:
+ set_2regs(0x10, 0x1a);
+ set_2regs(0x11, 0x01);
+ set_2regs(0x12, 0xcb);
+ break;
+ case XFER_UDMA_5:
+ set_2regs(0x10, 0x1a);
+ set_2regs(0x11, 0x02);
+ set_2regs(0x12, 0xcb);
+ break;
+ case XFER_UDMA_4:
+ set_2regs(0x10, 0x1a);
+ set_2regs(0x11, 0x03);
+ set_2regs(0x12, 0xcd);
+ break;
+ case XFER_UDMA_3:
+ set_2regs(0x10, 0x1a);
+ set_2regs(0x11, 0x05);
+ set_2regs(0x12, 0xcd);
+ break;
+ case XFER_UDMA_2:
+ set_2regs(0x10, 0x2a);
+ set_2regs(0x11, 0x07);
+ set_2regs(0x12, 0xcd);
+ break;
+ case XFER_UDMA_1:
+ set_2regs(0x10, 0x3a);
+ set_2regs(0x11, 0x0a);
+ set_2regs(0x12, 0xd0);
+ break;
+ case XFER_UDMA_0:
+ set_2regs(0x10, 0x4a);
+ set_2regs(0x11, 0x0f);
+ set_2regs(0x12, 0xd5);
+ break;
+ case XFER_MW_DMA_2:
+ set_2regs(0x0e, 0x69);
+ set_2regs(0x0f, 0x25);
+ break;
+ case XFER_MW_DMA_1:
+ set_2regs(0x0e, 0x6b);
+ set_2regs(0x0f, 0x27);
+ break;
+ case XFER_MW_DMA_0:
+ set_2regs(0x0e, 0xdf);
+ set_2regs(0x0f, 0x5f);
+ break;
+#endif
+ case XFER_PIO_4:
+ set_2regs(0x0c, 0x23);
+ set_2regs(0x0d, 0x09);
+ set_2regs(0x13, 0x25);
+ break;
+ case XFER_PIO_3:
+ set_2regs(0x0c, 0x27);
+ set_2regs(0x0d, 0x0d);
+ set_2regs(0x13, 0x35);
+ break;
+ case XFER_PIO_2:
+ set_2regs(0x0c, 0x23);
+ set_2regs(0x0d, 0x26);
+ set_2regs(0x13, 0x64);
+ break;
+ case XFER_PIO_1:
+ set_2regs(0x0c, 0x46);
+ set_2regs(0x0d, 0x29);
+ set_2regs(0x13, 0xa4);
+ break;
+ case XFER_PIO_0:
+ set_2regs(0x0c, 0xfb);
+ set_2regs(0x0d, 0x2b);
+ set_2regs(0x13, 0xac);
+ break;
+ default:
+ ;
+ }
}
- return ide_config_drive_speed(drive, speed);
+ return err;
}
/* 0 1 2 3 4 5 6 7 8
{
struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4);
- unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
+ unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20);
+ /* Enable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */
if (drive->addressing) {
- unsigned long word_count = 0;
- u8 clock = IN_BYTE(high_16 + PDC_CLK);
+ unsigned long word_count = 0, hankval;
+ u32 clockreg = high_16 + PDC_CLK;
+ u8 clock = IN_BYTE(clockreg);
- outb(clock|(ch->unit ? 0x08 : 0x02), high_16 + PDC_CLK);
+ OUT_BYTE(clock | (ch->unit ? 0x08 : 0x02), clockreg);
word_count = (rq->nr_sectors << 8);
- word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
- outl(word_count, atapi_reg);
+ hankval = (rq_data_dir(rq) == READ) ? 0x05 << 24 : 0x06 << 24;
+ hankval |= word_count;
+ outl(hankval, atapi_port);
}
/* Note that this is done *after* the cmd has been issued to the drive,
{
struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4);
- unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
+ unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20);
unsigned long dma_base = ch->dma_base;
- u8 dma_stat, clock;
+ u8 dma_stat;
+ /* Disable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */
if (drive->addressing) {
- outl(0, atapi_reg); /* zero out extra */
- clock = IN_BYTE(high_16 + PDC_CLK);
- OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + PDC_CLK);
+ u32 clockreg = high_16 + PDC_CLK;
+ u8 clock;
+
+ outl(0, atapi_port); /* zero out extra */
+ clock = IN_BYTE(clockreg);
+ OUT_BYTE(clock & ~(ch->unit ? 0x08 : 0x02), clockreg);
}
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
#endif
-static void pdc202xx_new_reset(struct ata_device *drive)
+/* FIXME: use generic ata_reset() --bzolnier */
+static void pdc202xx_reset(struct ata_device *drive)
{
- ata_reset(drive->channel);
- mdelay(1000);
- ata_irq_enable(drive, 1);
- mdelay(1000);
+ outb(0x04, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
+ udelay(10);
+ outb(0x00, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
printk(KERN_INFO "PDC202XX: %s channel reset.\n",
- drive->channel->unit ? "Secondary" : "Primary");
+ drive->channel->unit ? "Secondary" : "Primary");
}
/*
* software host reset
*
* BIOS will set UDMA timing on if the drive supports it.
- * The user may then want to turn it off. A bug is that
+ * The user may then want to turn it off. A bug is
* that device cannot handle a downgrade in timing from
* UDMA to DMA. Disk accesses after issuing a set
* feature command will result in errors.
* A software reset leaves the timing registers intact,
* but resets the drives on both channels.
*/
+#if 0
static void pdc202xx_reset_host(struct pci_dev *dev)
{
u32 high_16 = pci_resource_start(dev, 4);
printk(KERN_INFO "%s: channel needs reset.\n", ch->name);
pdc202xx_reset_host(ch->pci_dev);
}
+#endif
static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
{
u32 high_16 = pci_resource_start(dev, 4);
- u8 burst = IN_BYTE(high_16 + PDC_UDMA);
+ u32 burstreg = high_16 + PDC_UDMA;
+ u8 burst = IN_BYTE(burstreg);
+
+ set_reg_and_wait(burst | 0x10, burstreg, 100);
+ /* FIXME: 2 seconds ?! */
+ set_reg_and_wait(burst & ~0x10, burstreg, 2000);
if (dev->resource[PCI_ROM_RESOURCE].start) {
pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start);
}
+#if 0
switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265:
pdc202xx_reset_host(dev);
break;
default:
- /* FIXME: only checked for 20246 - is this right?,
- if it is needed it should go to ide-pci --bkz */
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
byte irq = 0, irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
}
break;
}
+#endif
#ifdef CONFIG_PDC202XX_BURST
if (!(burst & 1)) {
printk(KERN_INFO "%s: forcing (U)DMA BURST.\n", dev->name);
- OUT_BYTE(burst | 1, high_16 + PDC_UDMA);
+ OUT_BYTE(burst | 1, burstreg);
+ burst = IN_BYTE(burstreg);
}
#endif
printk(KERN_INFO "%s: (U)DMA BURST %sabled, "
return dev->irq;
}
+#if 0
/* chipsets newer then 20267 */
static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev)
{
}
return dev->irq;
}
+#endif
static unsigned int __init pdc202xx_ata66_check(struct ata_channel *ch)
{
{
hwif->tuneproc = &pdc202xx_tune_drive;
hwif->quirkproc = &check_in_drive_lists;
+ hwif->resetproc = &pdc202xx_reset;
switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20276:
+ case PCI_DEVICE_ID_PROMISE_20275:
+ case PCI_DEVICE_ID_PROMISE_20271:
case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20268:
case PCI_DEVICE_ID_PROMISE_20268R:
hwif->udma_four = pdc202xx_tx_ata66_check(hwif);
hwif->speedproc = &pdc202xx_new_tune_chipset;
- hwif->resetproc = &pdc202xx_new_reset;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base)
hwif->udma_setup = pdc202xx_tx_udma_setup;
break;
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265:
- case PCI_DEVICE_ID_PROMISE_20262:
- hwif->udma_four = pdc202xx_ata66_check(hwif);
-
- hwif->resetproc = &pdc202xx_reset;
#ifdef CONFIG_BLK_DEV_IDEDMA
/* we need special functions for lba48 */
if (hwif->dma_base) {
hwif->udma_stop = pdc202xx_udma_stop;
}
#endif
- /* FIXME: check whether 20246 works with lba48 --bkz */
+ /* PDC20262 doesn't support LBA48 */
+ case PCI_DEVICE_ID_PROMISE_20262:
+ hwif->udma_four = pdc202xx_ata66_check(hwif);
+
case PCI_DEVICE_ID_PROMISE_20246:
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base)
{
vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20268,
- init_chipset: pdc202xx_tx_init_chipset,
+ init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA
{
vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20268R,
- init_chipset: pdc202xx_tx_init_chipset,
+ init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA
{
vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20269,
- init_chipset: pdc202xx_tx_init_chipset,
+ init_chipset: pdc202xx_init_chipset,
+ init_channel: ide_init_pdc202xx,
+ bootable: OFF_BOARD,
+ flags: ATA_F_IRQ | ATA_F_DMA
+ },
+ {
+ vendor: PCI_VENDOR_ID_PROMISE,
+ device: PCI_DEVICE_ID_PROMISE_20271,
+ init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA
{
vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20275,
- init_chipset: pdc202xx_tx_init_chipset,
+ init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA
{
vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20276,
- init_chipset: pdc202xx_tx_init_chipset,
+ init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA
rq->nr_sectors -= nsect;
total_remaining = rq->nr_sectors;
if ((rq->current_nr_sectors -= nsect) <= 0)
- __ata_end_request(drive, rq, 1, 0);
+ ata_end_request(drive, rq, 1, 0);
/*
* Now the data has been read in, do the following:
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif
- __ata_end_request(drive, rq, 1, rq->nr_sectors);
+ ata_end_request(drive, rq, 1, rq->nr_sectors);
return ATA_OP_FINISHED;
}
/* Check that it's a regular command. If not, bomb out early. */
if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "pdc4030 bad flags");
- __ata_end_request(drive, rq, 0, 0);
+ ata_end_request(drive, rq, 0, 0);
return ATA_OP_FINISHED;
}
default:
printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
- __ata_end_request(drive, rq, 0, 0);
+ ata_end_request(drive, rq, 0, 0);
return ATA_OP_FINISHED;
}
}
Authors: Arjan van de Ven <arjanv@redhat.com>
- Based on work done by Søren Schmidt for FreeBSD
+ Based on work done by Søren Schmidt for FreeBSD
*/
}
}
- /* There used to be code here that assigned drive->id->CHS
- to drive->CHS and that to drive->bios_CHS. However, some disks have
- id->C/H/S = 4092/16/63 but are larger than 2.1 GB. In such cases
- that code was wrong. Moreover, there seems to be no reason to do
- any of these things. */
+ /* There used to be code here that assigned drive->id->CHS to
+ * drive->CHS and that to drive->bios_CHS. However, some disks have
+ * id->C/H/S = 4092/16/63 but are larger than 2.1 GB. In such cases
+ * that code was wrong. Moreover, there seems to be no reason to do
+ * any of these things.
+ *
+ * Please note that recent RedHat changes to the disk utils are bogous
+ * and will report spurious errors.
+ */
/* translate? */
if (drive->forced_geom)
}
/*
- * hd_driveid data come as little endian, it needs to be converted on big
- * endian machines.
+ * Drive ID data come as little endian, it needs to be converted on big endian
+ * machines.
*/
void ata_fix_driveid(struct hd_driveid *id)
{
outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2);
#endif
- /* Don't use ide_wait_cmd here - it will attempt to set_geometry and
- * recalibrate, but for some reason these don't work at this point
- * (lost interrupt).
- *
- * Select the drive, and issue the SETFEATURES command
+ /*
+ * Select the drive, and issue the SETFEATURES command.
*/
disable_irq(ch->irq); /* disable_irq_nosync ?? */
udelay(1);
udelay(1);
ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_CMD, NULL);
ata_mask(drive);
-
enable_irq(ch->irq);
if (ret != ATA_OP_READY) {
gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL);
if (!gd->sizes)
goto err_kmalloc_gd_sizes;
+ memset(gd->sizes, 0, ATA_MINORS*sizeof(gd->sizes[0]));
gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
if (!gd->part)
ar->XXX_handler = tcq_nop_handler;
ar->command_type = IDE_DRIVE_TASK_NO_DATA;
- rq->rq_dev = mk_kdev(drive->channel->major, (drive->select.b.unit)<<PARTN_BITS);
_elv_add_request(q, rq, 0, 0);
out:
TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag);
- __ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
+ ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
/*
* we completed this command, check if we can service a new command
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
- if (check_region(0x108, 2)) {
+ if (!request_region(0x108, 2, "umc8672")) {
__restore_flags(flags);
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return;
if (in_umc (0xd5) != 0xa0)
{
__restore_flags(flags); /* local CPU only */
+ release_region(0x108, 2);
printk ("umc8672: not found\n");
return;
}
umc_set_speeds (current_speeds);
__restore_flags(flags); /* local CPU only */
- request_region(0x108, 2, "umc8672");
ide_hwifs[0].chipset = ide_umc8672;
ide_hwifs[1].chipset = ide_umc8672;
ide_hwifs[0].tuneproc = &tune_umc;
u8 *scsi_buf;
if (!(rq->flags & REQ_PC)) {
- __ata_end_request(drive, rq, uptodate, 0);
+ ata_end_request(drive, rq, uptodate, 0);
return 0;
}
MOD_DEC_USE_COUNT;
}
+static Scsi_Host_Template template;
static int idescsi_cleanup (struct ata_device *drive)
{
- struct Scsi_Host *host = drive->driver_data;
-
if (ide_unregister_subdriver (drive)) {
return 1;
}
- scsi_unregister(host);
+ scsi_unregister_host(&template);
return 0;
}
static void __exit exit_idescsi_module(void)
{
unregister_ata_driver(&ata_ops);
- scsi_unregister_host(&template);
}
module_init(init_idescsi_module);
} s;
};
-extern void atapi_init_pc(struct atapi_packet_command *pc);
-
-extern void atapi_discard_data(struct ata_device *, unsigned int);
-extern void atapi_write_zeros(struct ata_device *, unsigned int);
-
-extern void atapi_read(struct ata_device *, u8 *, unsigned int);
-extern void atapi_write(struct ata_device *, u8 *, unsigned int);
-
-
/*
* ATAPI Status Register.
*/
u8 sk_specific[2]; /* Sense Key Specific */
u8 pad[2]; /* Padding to 20 bytes */
} atapi_request_sense_result_t;
+
+
+extern void atapi_init_pc(struct atapi_packet_command *pc);
+
+extern void atapi_discard_data(struct ata_device *, unsigned int);
+extern void atapi_write_zeros(struct ata_device *, unsigned int);
+
+extern void atapi_read(struct ata_device *, u8 *, unsigned int);
+extern void atapi_write(struct ata_device *, u8 *, unsigned int);
+
+typedef enum {
+ ide_wait, /* insert rq at end of list, and wait for it */
+ ide_preempt, /* insert rq in front of current request */
+ ide_end /* insert rq at end of list, but don't wait for it */
+} ide_action_t;
+
+extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
#ifndef _IDE_H
#define _IDE_H
+
/*
* Copyright (C) 1994-2002 Linus Torvalds & authors
*/
*/
#define ERROR_MAX 8 /* Max read/write errors per sector */
#define ERROR_RESET 3 /* Reset controller every 4th retry */
-#define ERROR_RECAL 1 /* Recalibrate every 2nd retry */
/*
- * state flags
+ * State flags.
*/
#define DMA_PIO_RETRY 1 /* retrying in PIO */
/*
- * Definitions for accessing IDE controller registers
+ * Definitions for accessing IDE controller registers.
*/
enum {
* Structure to hold all information about the location of this port
*/
typedef struct hw_regs_s {
- ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
- int irq; /* our irq number */
- int dma; /* our dma entry */
- ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
+ ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
+ int irq; /* our irq number */
+ int dma; /* our dma entry */
+ int (*ack_intr)(struct ata_channel *); /* acknowledge interrupt */
hwif_chipset_t chipset;
} hw_regs_t;
/*
* Set up hw_regs_t structure before calling ide_register_hw (optional)
*/
-void ide_setup_ports(hw_regs_t *hw,
- ide_ioreg_t base,
- int *offsets,
- ide_ioreg_t ctrl,
- ide_ioreg_t intr,
- ide_ack_intr_t *ack_intr,
- int irq);
+extern void ide_setup_ports(hw_regs_t *hw,
+ ide_ioreg_t base, int *offsets,
+ ide_ioreg_t ctrl, ide_ioreg_t intr,
+ int (*ack_intr)(struct ata_channel *),
+ int irq);
#include <asm/ide.h>
unsigned int usage; /* current "open()" count for drive */
char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */
- /* NOTE: If we had proper separation between channel and host chip, we
- * could move this to the channel and many sync problems would
- * magically just go away.
- */
- request_queue_t queue; /* per device request queue */
+ request_queue_t queue; /* per device request queue */
struct request *rq; /* current request */
- unsigned long sleep; /* sleep until this time */
+ unsigned long sleep; /* sleep until this time */
byte retry_pio; /* retrying dma capable host in pio */
byte state; /* retry state */
void *driver_data; /* extra driver data */
devfs_handle_t de; /* directory for device */
+
char driver_req[10]; /* requests specific driver */
int last_lun; /* last logical unit */
enum {
IDE_BUSY, /* awaiting an interrupt */
IDE_SLEEP,
+ IDE_PIO, /* PIO in progress */
IDE_DMA /* DMA in progress */
};
*/
spinlock_t *lock;
unsigned long *active; /* active processing request */
-
ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */
+
+ /* FIXME: Only still used in PDC4030. Localize this code there by
+ * replacing with busy waits.
+ */
struct timer_list timer; /* failsafe timer */
ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *); /* irq handler, if active */
unsigned long poll_timeout; /* timeout value during polled operations */
+
struct ata_device *drive; /* last serviced drive */
extern int ide_register_hw(hw_regs_t *hw);
extern void ide_unregister(struct ata_channel *);
-struct ata_taskfile;
-
#define IDE_MAX_TAG 32
#ifdef CONFIG_BLK_DEV_IDE_TCQ
#define DEVICE_NR(device) (minor(device) >> PARTN_BITS)
#include <linux/blk.h>
-extern int __ata_end_request(struct ata_device *, struct request *, int, unsigned int);
-
+extern int ata_end_request(struct ata_device *, struct request *, int, unsigned int);
extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
unsigned long timeout, ata_expiry_t expiry);
*/
struct ata_device *get_info_ptr(kdev_t i_rdev);
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum {
- ide_wait, /* insert rq at end of list, and wait for it */
- ide_preempt, /* insert rq in front of current request */
- ide_end /* insert rq at end of list, but don't wait for it */
-} ide_action_t;
-
/*
* temporarily mapping a (possible) highmem bio for PIO transfer
*/
#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
-extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
-
struct ata_taskfile {
struct hd_drive_task_hdr taskfile;
struct hd_drive_task_hdr hobfile;
extern void ata_write(struct ata_device *, void *, unsigned int);
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *);
-extern void ide_fix_driveid(struct hd_driveid *id);
extern int ide_config_drive_speed(struct ata_device *, byte);
extern byte eighty_ninty_three(struct ata_device *);
#define DRIVE_LOCK(drive) ((drive)->queue.queue_lock)
-extern int drive_is_ready(struct ata_device *drive);
-
/* Low level device access functions. */
extern void ata_select(struct ata_device *, unsigned long);
extern void ata_mask(struct ata_device *);
extern int ata_status(struct ata_device *, u8, u8);
+extern int ata_status_irq(struct ata_device *drive);
extern int ata_status_poll( struct ata_device *, u8, u8,
unsigned long, struct request *rq);
#define PCI_DEVICE_ID_PROMISE_20268 0x4d68
#define PCI_DEVICE_ID_PROMISE_20268R 0x6268
#define PCI_DEVICE_ID_PROMISE_20269 0x4d69
+#define PCI_DEVICE_ID_PROMISE_20271 0x6269
#define PCI_DEVICE_ID_PROMISE_20275 0x1275
#define PCI_DEVICE_ID_PROMISE_20276 0x5275
#define PCI_DEVICE_ID_PROMISE_5300 0x5300