Commit e9356da8 authored by Martin Dalecki's avatar Martin Dalecki Committed by Trond Myklebust

[PATCH] 2.5.26 IDE 99

Most noticable in the patch:

1. we handle IRQ sharing now better then ever

2. survives quite a lot of testing by few people. Forexample
cat /dev/hdb > /dev/null, where /dev/hdb contains a CD-ROM
with a big cratch on the surface making sure it's broken :-).
it's BTW. amanzing how wide the cratch had to be until errors
ocurred.

3. Doesn't play with rq_rdev and friends

Fri Jul 12 05:04:32 CEST 2002 ide-clean-99

- Push nIEN disabling down at the place where we are finished with a particular
   request.

- First round of command line parser cleanups by Gerald Champagne.

- Unfold the drive eviction functions in do_request(). This allowed us to
   realize that we don't have to re-get the major/minor numbers of the device we
   are action on from the raw device field of the currently running request. One
   significant place less in kernel where major/minor data gets manipulated.

- Move the big IDE_BUSY loop out of do_request to do_ide_request().  This makes
   us realize that we don't have to clear the IDE_BUSY bit just before
   reentering do_request to look for more requests still pending on the queue
   and set it immediately again.

   This is fixing a tinny race on the code path from IRQ or timer function,
   where we had a tinny window between the clearing of the IDE_BUSY bit and
   reentering the request queue for completely unrelated requests to come in to
   our way.

- Don't return any value in do_reset1(). It's always ATA_OP_CONTINUES. Split it
   up in to two functions one for disks (well in fact channels) and one for
   ATAPI devices. It turns out that they can be moved to the places where they
   are used to clarify the code flow. The only function remaining is
   do_reset_channel() now.

- Duplicate code from ide_do_drive_code explicitely in ide_raw_taskfile().
   Simplify ide_raw_taskfile() thereafter. Realize that ide_do_drive_cmd()
   is now only used by ATAPI devices. Move it therefore to atapi.c.

- Do busy polling for ATAPI reset operations. This is much safer then the
   previous timer games played there. It simply doesn't make sense to give the
   bus up during such a subtile operation. We don't have to disable IRQs here as
   well, since we are already under the protection of the do_request mechanisms.
   (Well hopefully...)

- Remove no longer used reset_poll() function. poll_timeout and friends are now
   used only in pdc4030 code. Those function where not called from IRQ context
   but they where set as handlers and not as expiry functions.

- Return ATA_OP_CONTINUES instead of ATA_OP_FINISHED in ata_error(), to signal
   that we are willing to retry the operation until the maximal number of retry
   attempts is exceeded. Returning ATA_OP_FINISHED without prior end_request()
   hangs the system.

- Apply trivia from DJ patch set.

- Apply small configuration fix to ide-pci.c from Muli Ben-Yehuda.

- Feed add_blkdev_randomness with information we already have in struct
   ata_channel *ch->major, instead of using the major(macro) on the request in
   question.

- Make ide_raw_taskfile use the same request submission mechanism as
   tcq_invalidate_queue(). Something similar would be ideal for ioctl() code as
   well.

- Implement actual device reset. Realize that the recalibration procedure is
   doomed by the standard. Don't try to recover by recalibrating devices
   therefore -just our retry mechanism should work in those cases. And suddenly
   the error handling code is IRQ safe.

- Reinvent the ATA reset operation, since it is apparently needed. We still
   have to do the whole transfer timing reconfiguration there.

- Move drive_is_ready(), which is in reality an attempt to check for IRQ
   requesters without clearing the IRQ line, over to the place where it belongs:
   device.c, which is the direct device access abstraction place.  Rename it to
   ata_status_irq() to prevent global name space pollution.

- Updates to the pdc202xxx host chip controller setup code by Bart³omiej
   ¯o³nierkiewicz:

   Forward port 2.4 patch by Hank Yang from Promise:

	- 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

- Mark TCQ as dangerous and add some bits about it to the help.

- Add some missing exports.

- Some small ide-scsi.c host allocation fixes by sullivan.
parent 3ec59360
...@@ -708,7 +708,14 @@ CONFIG_BLK_DEV_IDE_TCQ ...@@ -708,7 +708,14 @@ CONFIG_BLK_DEV_IDE_TCQ
Digital drives in the Expert series (by nature of really being IBM Digital drives in the Expert series (by nature of really being IBM
drives). 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 CONFIG_BLK_DEV_IDE_TCQ_DEPTH
Maximum size of commands to enable per-drive. Any value between 1 Maximum size of commands to enable per-drive. Any value between 1
......
...@@ -34,7 +34,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -34,7 +34,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI 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 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 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 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 if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32 int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/completion.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
...@@ -115,6 +116,66 @@ void atapi_write(struct ata_device *drive, u8 *buf, unsigned int n) ...@@ -115,6 +116,66 @@ void atapi_write(struct ata_device *drive, u8 *buf, unsigned int n)
outsw(IDE_DATA_REG, buf + (n & ~0x03), 1); 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_discard_data);
EXPORT_SYMBOL(atapi_write_zeros); EXPORT_SYMBOL(atapi_write_zeros);
EXPORT_SYMBOL(atapi_init_pc); EXPORT_SYMBOL(atapi_init_pc);
......
...@@ -79,6 +79,8 @@ void ata_mask(struct ata_device *drive) ...@@ -79,6 +79,8 @@ void ata_mask(struct ata_device *drive)
ch->maskproc(drive); ch->maskproc(drive);
} }
EXPORT_SYMBOL(ata_mask);
/* /*
* Check the state of the status register. * Check the state of the status register.
*/ */
...@@ -93,6 +95,39 @@ int ata_status(struct ata_device *drive, u8 good, u8 bad) ...@@ -93,6 +95,39 @@ int ata_status(struct ata_device *drive, u8 good, u8 bad)
EXPORT_SYMBOL(ata_status); 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 * 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 * all of the "good" bits and none of the "bad" bits, and if all is okay it
...@@ -210,6 +245,8 @@ void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) ...@@ -210,6 +245,8 @@ void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]); OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]);
} }
EXPORT_SYMBOL(ata_out_regfile);
/* /*
* Input a complete register file. * Input a complete register file.
*/ */
...@@ -223,5 +260,4 @@ void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) ...@@ -223,5 +260,4 @@ void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
rf->high_cylinder = IN_BYTE(ch->io_ports[IDE_HCYL_OFFSET]); rf->high_cylinder = IN_BYTE(ch->io_ports[IDE_HCYL_OFFSET]);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -106,9 +106,9 @@ static int gayle_ack_intr_a1200(struct ata_channel *hwif) ...@@ -106,9 +106,9 @@ static int gayle_ack_intr_a1200(struct ata_channel *hwif)
return 1; 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) void __init gayle_init(void)
{ {
...@@ -122,7 +122,7 @@ void __init gayle_init(void) ...@@ -122,7 +122,7 @@ void __init gayle_init(void)
for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
ide_ioreg_t base, ctrlport, irqport; ide_ioreg_t base, ctrlport, irqport;
ide_ack_intr_t *ack_intr; int (*ack_intr)(struct ata_channel *);
hw_regs_t hw; hw_regs_t hw;
int index; int index;
unsigned long phys_base, res_start, res_n; unsigned long phys_base, res_start, res_n;
......
...@@ -132,16 +132,16 @@ unsigned long last_req; ...@@ -132,16 +132,16 @@ unsigned long last_req;
unsigned long read_timer(void) unsigned long read_timer(void)
{ {
extern spinlock_t i8253_lock;
unsigned long t, flags; unsigned long t, flags;
int i; int i;
save_flags(flags); spin_lock_irqsave(&i8253_lock, flags);
cli();
t = jiffies * 11932; t = jiffies * 11932;
outb_p(0, 0x43); outb_p(0, 0x43);
i = inb_p(0x40); i = inb_p(0x40);
i |= inb(0x40) << 8; i |= inb(0x40) << 8;
restore_flags(flags); spin_unlock_irqrestore(&i8253_lock, flags);
return(t - i); return(t - i);
} }
#endif #endif
...@@ -817,8 +817,19 @@ static void __init hd_geninit(void) ...@@ -817,8 +817,19 @@ static void __init hd_geninit(void)
NR_HD = 0; NR_HD = 0;
return; return;
} }
request_region(HD_DATA, 8, "hd"); if (!request_region(HD_DATA, 8, "hd")) {
request_region(HD_CMD, 1, "hd(cmd)"); 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; hd_gendisk.nr_real = NR_HD;
......
...@@ -556,7 +556,7 @@ static void cdrom_end_request(struct ata_device *drive, struct request *rq, int ...@@ -556,7 +556,7 @@ static void cdrom_end_request(struct ata_device *drive, struct request *rq, int
if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors) if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
uptodate = 1; uptodate = 1;
__ata_end_request(drive, rq, uptodate, 0); ata_end_request(drive, rq, uptodate, 0);
} }
...@@ -912,7 +912,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request ...@@ -912,7 +912,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
if (dma) { if (dma) {
if (!dma_error) { 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; return ATA_OP_FINISHED;
} else } else
...@@ -1497,7 +1497,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request ...@@ -1497,7 +1497,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
if (dma_error) if (dma_error)
return ata_error(drive, rq, "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; return ATA_OP_FINISHED;
} }
...@@ -1936,7 +1936,7 @@ static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense) ...@@ -1936,7 +1936,7 @@ static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense)
If we get an error for the regular case, we assume If we get an error for the regular case, we assume
a CDI without additional audio tracks. In this case a CDI without additional audio tracks. In this case
the readable TOC is empty (CDI tracks are not included) 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; ntracks = 0;
stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0, stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
(char *)&toc->hdr, (char *)&toc->hdr,
...@@ -2840,11 +2840,11 @@ static int ide_cdrom_setup(struct ata_device *drive) ...@@ -2840,11 +2840,11 @@ static int ide_cdrom_setup(struct ata_device *drive)
} }
/* Forwarding functions to generic routines. */ /* 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, struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) 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) static int ide_cdrom_open (struct inode *ip, struct file *fp, struct ata_device *drive)
......
...@@ -140,7 +140,7 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq ...@@ -140,7 +140,7 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
--rq->current_nr_sectors; --rq->current_nr_sectors;
if (rq->current_nr_sectors <= 0) { 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); // printk("Request Ended stat: %02x\n", drive->status);
return ATA_OP_FINISHED; return ATA_OP_FINISHED;
...@@ -166,7 +166,7 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r ...@@ -166,7 +166,7 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r
if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) if (!ata_status(drive, DRIVE_READY, drive->bad_wstat))
return ata_error(drive, rq, __FUNCTION__); 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; ret = ATA_OP_FINISHED;
} else { } else {
if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) { if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) {
...@@ -235,7 +235,7 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request ...@@ -235,7 +235,7 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
/* FIXME: this seems buggy */ /* FIXME: this seems buggy */
if (rq->current_nr_sectors <= 0) { 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; return ATA_OP_FINISHED;
} }
msect -= nsect; msect -= nsect;
...@@ -269,7 +269,7 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -269,7 +269,7 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
return ata_error(drive, rq, __FUNCTION__); return ata_error(drive, rq, __FUNCTION__);
} }
if (!rq->nr_sectors) { 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; rq->bio = NULL;
ret = ATA_OP_FINISHED; ret = ATA_OP_FINISHED;
} else if (!ok) { } else if (!ok) {
...@@ -349,7 +349,7 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -349,7 +349,7 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
/* FIXME: this check doesn't make sense */ /* FIXME: this check doesn't make sense */
if (!(rq->flags & REQ_CMD)) { if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "idedisk_do_request - bad command"); 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; return ATA_OP_FINISHED;
} }
...@@ -514,8 +514,8 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -514,8 +514,8 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
printk("sectors=%ld, ", rq->nr_sectors); printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n", rq->buffer); printk("buffer=%p\n", rq->buffer);
#endif #endif
ar->cmd = cmd; ar->cmd = cmd;
rq->special = ar; rq->special = ar;
} }
/* (ks/hs): Moved to start, do not use for multiple out commands. /* (ks/hs): Moved to start, do not use for multiple out commands.
...@@ -548,10 +548,9 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -548,10 +548,9 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
return ATA_OP_CONTINUES; return ATA_OP_CONTINUES;
} }
/* FIXME: Warning check for race between handler and prehandler /* FIXME: Warning check for race between handlers for writing
* for writing first block of data. however since we are well * first block of data. However since we are well inside the
* inside the boundaries of the seek, we should be okay. * boundaries of the seek, we should be okay.
* FIXME: should be fixed --bzolnier
*/ */
if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) { if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) {
ide_startstop_t ret; ide_startstop_t ret;
...@@ -596,13 +595,15 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -596,13 +595,15 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
* *
* FIXME: Replace hard-coded 100, what about * FIXME: Replace hard-coded 100, what about
* error handling? * error handling?
*
* FIXME: Whatabout the IRE clearing and not clearing case?!
*/ */
for (i = 0; i < 100; ++i) { for (i = 0; i < 100; ++i) {
if (drive_is_ready(drive)) if (ata_status_irq(drive))
break; break;
} }
if (!drive_is_ready(drive)) { if (!ata_status_irq(drive)) {
/* We are compleatly missing an error /* We are compleatly missing an error
* return path here. * return path here.
* FIXME: We have only one? -alat * FIXME: We have only one? -alat
...@@ -1290,7 +1291,9 @@ static int idedisk_cleanup(struct ata_device *drive) ...@@ -1290,7 +1291,9 @@ static int idedisk_cleanup(struct ata_device *drive)
return ret; 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; struct hd_driveid *id = drive->id;
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/atapi.h> #include <linux/atapi.h>
#include <linux/buffer_head.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -367,7 +368,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i ...@@ -367,7 +368,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i
return 0; return 0;
if (!(rq->flags & REQ_SPECIAL)) { if (!(rq->flags & REQ_SPECIAL)) {
__ata_end_request(drive, rq, uptodate, 0); ata_end_request(drive, rq, uptodate, 0);
return 0; return 0;
} }
...@@ -731,7 +732,6 @@ static ide_startstop_t idefloppy_transfer_pc2(struct ata_device *drive, struct r ...@@ -731,7 +732,6 @@ static ide_startstop_t idefloppy_transfer_pc2(struct ata_device *drive, struct r
static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq) static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq)
{ {
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
ide_startstop_t startstop;
atapi_ireason_reg_t ireason; atapi_ireason_reg_t ireason;
int ret; int ret;
......
...@@ -50,7 +50,7 @@ static void print_fixed (volatile unsigned char *p); ...@@ -50,7 +50,7 @@ static void print_fixed (volatile unsigned char *p);
static void print_funcid (int func); static void print_funcid (int func);
static int check_ide_device (unsigned long base); 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); static void m8xx_ide_tuneproc(struct ata_device *drive, byte pio);
typedef struct ide_ioport_desc { typedef struct ide_ioport_desc {
...@@ -326,7 +326,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ...@@ -326,7 +326,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
/* register routine to tune PIO mode */ /* register routine to tune PIO mode */
ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; 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, /* Enable Harddisk Interrupt,
* and make it edge sensitive * and make it edge sensitive
*/ */
...@@ -401,7 +401,7 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, ...@@ -401,7 +401,7 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
ioport_dsc[data_port].reg_off[i], ioport_dsc[data_port].reg_off[i],
i, base + ioport_dsc[data_port].reg_off[i]); i, base + ioport_dsc[data_port].reg_off[i]);
#endif #endif
*p++ = base + ioport_dsc[data_port].reg_off[i]; *p++ = base + ioport_dsc[data_port].reg_off[i];
} }
if (irq) { if (irq) {
...@@ -412,16 +412,16 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, ...@@ -412,16 +412,16 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
/* register routine to tune PIO mode */ /* register routine to tune PIO mode */
ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; 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, /* Enable Harddisk Interrupt,
* and make it edge sensitive * and make it edge sensitive
*/ */
/* (11-18) Set edge detect for irq, no wakeup from low power mode */ /* (11-18) Set edge detect for irq, no wakeup from low power mode */
((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
(0x80000000 >> ioport_dsc[data_port].irq); (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
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
...@@ -493,11 +493,10 @@ m8xx_ide_tuneproc(struct ata_device *drive, byte pio) ...@@ -493,11 +493,10 @@ m8xx_ide_tuneproc(struct ata_device *drive, byte pio)
printk("%s[%d] %s: not implemented yet!\n", printk("%s[%d] %s: not implemented yet!\n",
__FILE__,__LINE__,__FUNCTION__); __FILE__,__LINE__,__FUNCTION__);
#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */ #endif
} }
static void static int ide_interrupt_ack(struct ata_channel *ch)
ide_interrupt_ack (void *dev)
{ {
#ifdef CONFIG_IDE_8xx_PCCARD #ifdef CONFIG_IDE_8xx_PCCARD
u_int pscr, pipr; u_int pscr, pipr;
...@@ -529,17 +528,17 @@ ide_interrupt_ack (void *dev) ...@@ -529,17 +528,17 @@ ide_interrupt_ack (void *dev)
/* clear the interrupt sources */ /* clear the interrupt sources */
((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr; ((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 * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
* MPC8xx's PCMCIA controller, so there is nothing to be done here * MPC8xx's PCMCIA controller, so there is nothing to be done here
* for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT. * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
* The interrupt is handled somewhere else. -- Steven * The interrupt is handled somewhere else. -- Steven
*/ */
#endif /* CONFIG_IDE_8xx_PCCARD */ #endif
}
return 0;
}
/* /*
* CIS Tupel codes * CIS Tupel codes
...@@ -655,7 +654,7 @@ static int check_ide_device (unsigned long base) ...@@ -655,7 +654,7 @@ static int check_ide_device (unsigned long base)
q+= 2; q+= 2;
} }
} }
#endif /* DEBUG_PCMCIA */ #endif
switch (code) { switch (code) {
case CISTPL_VERS_1: case CISTPL_VERS_1:
ident = p + 4; ident = p + 4;
......
...@@ -158,6 +158,80 @@ static int __init setup_pci_baseregs(struct pci_dev *dev, const char *name) ...@@ -158,6 +158,80 @@ static int __init setup_pci_baseregs(struct pci_dev *dev, const char *name)
return 0; 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. * Setup a particular port on an ATA host controller.
* *
...@@ -171,7 +245,6 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -171,7 +245,6 @@ static int __init setup_host_channel(struct pci_dev *dev,
int autodma) int autodma)
{ {
unsigned long base = 0; unsigned long base = 0;
unsigned long dma_base;
unsigned long ctl = 0; unsigned long ctl = 0;
ide_pci_enablebit_t *e = &(d->enablebits[port]); ide_pci_enablebit_t *e = &(d->enablebits[port]);
struct ata_channel *ch; struct ata_channel *ch;
...@@ -260,69 +333,13 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -260,69 +333,13 @@ static int __init setup_host_channel(struct pci_dev *dev,
if (ch->udma_four) if (ch->udma_four)
printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name); printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
/* /*
* Setup DMA transfers on the channel. * Setup DMA transfers on the channel.
*/ */
if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80)))) setup_channel_dma(dev, d, autodma, ch);
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);
#endif #endif
no_dma: no_dma:
/* Call chipset-specific routine for each enabled channel. */ /* Call chipset-specific routine for each enabled channel. */
if (d->init_channel) if (d->init_channel)
......
...@@ -421,6 +421,7 @@ ...@@ -421,6 +421,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/atapi.h> #include <linux/atapi.h>
#include <linux/buffer_head.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -2445,7 +2446,7 @@ static ide_startstop_t idetape_do_request(struct ata_device *drive, struct reque ...@@ -2445,7 +2446,7 @@ static ide_startstop_t idetape_do_request(struct ata_device *drive, struct reque
* We do not support buffer cache originated requests. * 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); 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; return ATA_OP_FINISHED;
} }
......
...@@ -33,18 +33,9 @@ ...@@ -33,18 +33,9 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/bitops.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. * Data transfer functions for polled IO.
*/ */
static void ata_read_32(struct ata_device *drive, void *buffer, unsigned int wcount) static void ata_read_32(struct ata_device *drive, void *buffer, unsigned int wcount)
{ {
insl(IDE_DATA_REG, buffer, wcount); insl(IDE_DATA_REG, buffer, wcount);
...@@ -143,103 +134,10 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount) ...@@ -143,103 +134,10 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int 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. * Invoked on completion of a special REQ_SPECIAL command.
*/ */
static ide_startstop_t special_intr(struct ata_device *drive, struct static ide_startstop_t special_intr(struct ata_device *drive, struct request *rq) {
request *rq) {
unsigned long flags; unsigned long flags;
struct ata_channel *ch =drive->channel; struct ata_channel *ch =drive->channel;
struct ata_taskfile *ar = rq->special; struct ata_taskfile *ar = rq->special;
...@@ -290,21 +188,52 @@ static ide_startstop_t special_intr(struct ata_device *drive, struct ...@@ -290,21 +188,52 @@ static ide_startstop_t special_intr(struct ata_device *drive, struct
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar, char *buf) 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->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)); wait_for_completion(&wait); /* wait for it to be serviced */
req.flags = REQ_SPECIAL;
req.buffer = buf;
req.special = ar;
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_read);
EXPORT_SYMBOL(ata_write); EXPORT_SYMBOL(ata_write);
EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_raw_taskfile);
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
...@@ -106,7 +105,7 @@ int drive_is_flashcard(struct ata_device *drive) ...@@ -106,7 +105,7 @@ int drive_is_flashcard(struct ata_device *drive)
return 0; 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; unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
...@@ -132,7 +131,7 @@ int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate ...@@ -132,7 +131,7 @@ int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate
} }
if (!end_that_request_first(rq, uptodate, nr_secs)) { 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)) if (!blk_rq_tagged(rq))
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
else else
...@@ -192,12 +191,13 @@ static void check_crc_errors(struct ata_device *drive) ...@@ -192,12 +191,13 @@ static void check_crc_errors(struct ata_device *drive)
if (mode > XFER_UDMA_0) if (mode > XFER_UDMA_0)
mode--; mode--;
else else
/* /*
* OOPS we do not goto non Ultra DMA modes * We do not do non Ultra DMA modes. Without iCRC's
* without iCRC's available we force * available, we force the system to PIO and make the
* the system to PIO and make the user * user select the ATA-1 ATA-2 DMA modes himself.
* invoke the ATA-1 ATA-2 DMA modes.
*/ */
mode = XFER_PIO_4; mode = XFER_PIO_4;
drive->channel->speedproc(drive, mode); drive->channel->speedproc(drive, mode);
...@@ -220,157 +220,9 @@ sector_t ata_capacity(struct ata_device *drive) ...@@ -220,157 +220,9 @@ sector_t ata_capacity(struct ata_device *drive)
if (ata_ops(drive) && ata_ops(drive)->capacity) if (ata_ops(drive) && ata_ops(drive)->capacity)
return ata_ops(drive)->capacity(drive); 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; 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) static inline u32 read_24(struct ata_device *drive)
{ {
return (IN_BYTE(IDE_HCYL_REG) << 16) | return (IN_BYTE(IDE_HCYL_REG) << 16) |
...@@ -489,58 +341,11 @@ u8 ata_dump(struct ata_device *drive, struct request * rq, const char *msg) ...@@ -489,58 +341,11 @@ u8 ata_dump(struct ata_device *drive, struct request * rq, const char *msg)
return err; 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. * 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) ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const char *msg)
{ {
...@@ -549,12 +354,9 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -549,12 +354,9 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
err = ata_dump(drive, rq, msg); err = ata_dump(drive, rq, msg);
/* FIXME: at least !drive check is bogus --bzolnier */ /* Only try to recover from block I/O operations.
if (!drive || !rq) */
return ATA_OP_FINISHED; if (!rq || !(rq->flags & REQ_CMD)) {
/* retry only "normal" I/O: */
if (!(rq->flags & REQ_CMD)) {
rq->errors = 1; rq->errors = 1;
return ATA_OP_FINISHED; return ATA_OP_FINISHED;
...@@ -562,10 +364,11 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -562,10 +364,11 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
/* other bits are useless when BUSY */ /* other bits are useless when BUSY */
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr))
rq->errors |= ERROR_RESET; /* FIXME: What's that?! */ rq->errors |= ERROR_RESET;
else { else if (drive->type == ATA_DISK) {
if (drive->type == ATA_DISK && (stat & ERR_STAT)) { /* The error bit has different meaning on cdrom and tape.
/* err has different meaning on cdrom and tape */ */
if (stat & ERR_STAT) {
if (err == ABRT_ERR) { if (err == ABRT_ERR) {
if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
return ATA_OP_FINISHED; /* some newer drives don't support WIN_SPECIFY */ return ATA_OP_FINISHED; /* some newer drives don't support WIN_SPECIFY */
...@@ -573,109 +376,128 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -573,109 +376,128 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
drive->crc_count++; /* UDMA crc error -- just retry the operation */ drive->crc_count++; /* UDMA crc error -- just retry the operation */
else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
rq->errors = ERROR_MAX; 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) /* As an alternative to resetting the drive, we try to clear
try_to_flush_leftover_data(drive); * 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)) 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) { if (rq->errors >= ERROR_MAX) {
printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name); printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name);
if (ata_ops(drive) && ata_ops(drive)->end_request) if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, rq, 0); ata_ops(drive)->end_request(drive, rq, 0);
else else
__ata_end_request(drive, rq, 0, 0); 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;
if (unit >= MAX_DRIVES) { return ATA_OP_FINISHED;
printk(KERN_ERR "%s: bad device number: %s\n", ch->name, kdevname(rq->rq_dev));
goto kill_rq;
} }
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 if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
* innocent following sector. unsigned int unit;
*/ struct ata_channel *ch = drive->channel;
if (block == 0 && drive->remap_0_to_1 == 1) int ret;
block = 1; /* redirect MBR access to EZ-Drive partn table */
ata_select(drive, 0); /* For an ATAPI device, first try an ATAPI SRST.
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);
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)) { /* Reset all devices on channel.
printk(KERN_WARNING "%s: device type %d not supported\n", */
drive->name, drive->type);
goto kill_rq;
}
/* The normal way of execution is to pass and execute the request /* First, reset any device state data we were maintaining for
* handler down to the device type driver. * 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) { /* And now actually perform the reset operation.
ret = ata_ops(drive)->do_request(drive, rq, block); */
} else { printk("%s: ATA reset...\n", ch->name);
__ata_end_request(drive, rq, 0, 0); ata_select(drive, 20);
ret = ATA_OP_FINISHED; udelay(1);
} ata_irq_enable(drive, 0);
return ret;
kill_rq: /* This command actually looks suspicious, since I couldn't
if (ata_ops(drive) && ata_ops(drive)->end_request) * find it in any standard document.
ata_ops(drive)->end_request(drive, rq, 0); */
else OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]);
__ata_end_request(drive, rq, 0, 0); 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;
} }
/* /*
...@@ -689,218 +511,255 @@ void ide_stall_queue(struct ata_device *drive, unsigned long timeout) ...@@ -689,218 +511,255 @@ void ide_stall_queue(struct ata_device *drive, unsigned long timeout)
drive->sleep = timeout + jiffies; 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; struct ata_channel *ch;
int unit; struct ata_device *drive = NULL;
unsigned int unit;
for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_startstop_t ret;
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;
}
return sleep; __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
}
/* /*
* Select the next device which will be serviced. This selects only between * Select the next device which will be serviced. This selects
* devices on the same channel, since everything else will be scheduled on the * only between devices on the same channel, since everything
* queue level. * 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;
for (unit = 0; unit < MAX_DRIVES; ++unit) { 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; 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; continue;
/* This device still wants to remain idle. /* This device still wants to remain idle.
*/ */
if (drive->sleep && time_after(drive->sleep, jiffies)) if (tmp->sleep && time_after(tmp->sleep, jiffies))
continue; continue;
/* Take this device, if there is no device choosen thus far or /* Take this device, if there is no device choosen thus
* it's more urgent. * far or which is more urgent.
*/ */
if (!choice || (drive->sleep && (!choice->sleep || time_after(choice->sleep, drive->sleep)))) { if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
if (!blk_queue_plugged(&drive->queue)) if (!blk_queue_plugged(&tmp->queue))
choice = drive; drive = tmp;
} }
} }
if (choice) if (!drive) {
return choice; 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;
}
/* if (sleep) {
* Take a short snooze, and then wake up again. Just in case /*
* there are big differences in relative throughputs.. don't * Take a short snooze, and then wake up again. Just
* want to hog the cpu too much. * 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)) if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
sleep = jiffies + WAIT_MIN_SLEEP; sleep = jiffies + WAIT_MIN_SLEEP;
#if 1 #if 1
if (timer_pending(&channel->timer)) if (timer_pending(&channel->timer))
printk(KERN_ERR "%s: timer already active\n", __FUNCTION__); printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
#endif #endif
set_bit(IDE_SLEEP, channel->active); set_bit(IDE_SLEEP, channel->active);
mod_timer(&channel->timer, sleep); 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);
}
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.
*/
/* if (channel->drive && !channel->drive->using_tcq)
* Issue a new request. ata_irq_enable(channel->drive, 0);
* 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 */
while (!test_and_set_bit(IDE_BUSY, channel->active)) { return;
struct ata_channel *ch; }
struct ata_device *drive;
struct request *rq = NULL;
ide_startstop_t startstop;
int i;
/* this will clear IDE_BUSY, if appropriate */ /* Remember the last drive we where acting on.
drive = choose_urgent_device(channel); */
ch = drive->channel;
ch->drive = drive;
if (!drive) /* Feed commands to a drive until it barfs.
break; */
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 if (!ata_can_queue(drive)) {
* with us won't generate IRQ's during our activity. if (!ata_pending_commands(drive)) {
*/ clear_bit(IDE_BUSY, ch->active);
for (i = 0; i < MAX_HWIFS; ++i) { if (drive->using_tcq)
struct ata_channel *tmp = &ide_hwifs[i]; ata_irq_enable(drive, 0);
int j; }
break;
}
if (!tmp->present) drive->sleep = 0;
continue;
if (ch->lock != tmp->lock) if (test_bit(IDE_DMA, ch->active)) {
continue; printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
break;
}
/* Only care if there is any drive on the channel in /* There's a small window between where the queue could be
* question. * replugged while we are in here when using tcq (in which case
*/ * the queue is probably empty anyways...), so check and leave
for (j = 0; j < MAX_DRIVES; ++j) { * if appropriate. When not using tcq, this is still a severe
struct ata_device * other = &tmp->drives[j]; * BUG!
*/
if (blk_queue_plugged(&drive->queue)) {
BUG_ON(!drive->using_tcq);
break;
}
if (other->present) if (!(rq = elv_next_request(&drive->queue))) {
ata_irq_enable(other, 0); 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 BUG_ON(!(rq->flags & REQ_STARTED));
* 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;
}
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)) { /* bail early if we've exceeded max_failures */
printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name); if (drive->max_failures && (drive->failures > drive->max_failures))
break; goto kill_rq;
}
/* There's a small window between where the queue could block = rq->sector;
* 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 (!(rq = elv_next_request(&drive->queue))) { /* Strange disk manager remap.
if (!ata_pending_commands(drive)) */
clear_bit(IDE_BUSY, ch->active); if (rq->flags & REQ_CMD)
drive->rq = NULL; if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
break; block += drive->sect0;
}
/* If there are queued commands, we can't start a /* Yecch - this will shift the entire interval, possibly killing some
* non-fs request (really, a non-queuable command) * innocent following sector.
* until the queue is empty. */
*/ if (block == 0 && drive->remap_0_to_1 == 1)
if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive)) block = 1; /* redirect MBR access to EZ-Drive partn table */
break;
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 */ spin_lock_irq(ch->lock);
startstop = start_request(drive, rq);
spin_lock_irq(ch->lock);
/* command started, we are busy */ /* continue if command started, so we are busy */
} while (startstop != ATA_OP_CONTINUES); } while (ret != ATA_OP_CONTINUES);
/* make sure the BUSY bit is set */ /* make sure the BUSY bit is set */
/* FIXME: perhaps there is some place where we miss to set it? */ /* FIXME: perhaps there is some place where we miss to set it? */
// set_bit(IDE_BUSY, ch->active); // set_bit(IDE_BUSY, ch->active);
}
} }
void do_ide_request(request_queue_t *q) 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);
}
} }
/* /*
...@@ -908,7 +767,8 @@ void do_ide_request(request_queue_t *q) ...@@ -908,7 +767,8 @@ void do_ide_request(request_queue_t *q)
* also be invoked as a result of a "sleep" operation triggered by the * also be invoked as a result of a "sleep" operation triggered by the
* mod_timer() call in do_request. * 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) void ide_timer_expiry(unsigned long data)
{ {
...@@ -928,6 +788,8 @@ void ide_timer_expiry(unsigned long data) ...@@ -928,6 +788,8 @@ void ide_timer_expiry(unsigned long data)
* as timer expired), or we were "sleeping" to give other * as timer expired), or we were "sleeping" to give other
* devices a chance. Either way, we don't really want to * devices a chance. Either way, we don't really want to
* complain about anything. * complain about anything.
*
* FIXME: Do we really still have to clear IDE_BUSY here?
*/ */
if (test_and_clear_bit(IDE_SLEEP, ch->active)) if (test_and_clear_bit(IDE_SLEEP, ch->active))
...@@ -979,7 +841,7 @@ void ide_timer_expiry(unsigned long data) ...@@ -979,7 +841,7 @@ void ide_timer_expiry(unsigned long data)
__cli(); /* local CPU only, as if we were handling an interrupt */ __cli(); /* local CPU only, as if we were handling an interrupt */
if (ch->poll_timeout) { if (ch->poll_timeout) {
ret = handler(drive, drive->rq); ret = handler(drive, drive->rq);
} else if (drive_is_ready(drive)) { } else if (ata_status_irq(drive)) {
if (test_bit(IDE_DMA, ch->active)) if (test_bit(IDE_DMA, ch->active))
udma_irq_lost(drive); udma_irq_lost(drive);
(void) ide_ack_intr(ch); (void) ide_ack_intr(ch);
...@@ -1026,11 +888,10 @@ void ide_timer_expiry(unsigned long data) ...@@ -1026,11 +888,10 @@ void ide_timer_expiry(unsigned long data)
enable_irq(ch->irq); enable_irq(ch->irq);
spin_lock_irq(ch->lock); spin_lock_irq(ch->lock);
if (ret == ATA_OP_FINISHED) if (ret == ATA_OP_FINISHED) {
clear_bit(IDE_BUSY, ch->active); /* Reenter the request handling engine. */
do_request(ch);
/* Reenter the request handling engine */ }
do_request(ch);
} }
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
} }
...@@ -1060,32 +921,35 @@ void ide_timer_expiry(unsigned long data) ...@@ -1060,32 +921,35 @@ void ide_timer_expiry(unsigned long data)
*/ */
static void unexpected_irq(int irq) 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; int i;
for (i = 0; i < MAX_HWIFS; ++i) { for (i = 0; i < MAX_HWIFS; ++i) {
struct ata_channel *ch = &ide_hwifs[i]; struct ata_channel *ch = &ide_hwifs[i];
int j;
struct ata_device *drive; struct ata_device *drive;
if (!ch->present) if (!ch->present || ch->irq != irq)
continue; continue;
if (ch->irq != irq) for (j = 0; j < MAX_DRIVES; ++j) {
continue; drive = &ch->drives[j];
/* FIXME: this is a bit weak */ /* this drive is idle */
drive = &ch->drives[0]; if (ata_status(drive, READY_STAT, BAD_STAT))
continue;
if (!ata_status(drive, READY_STAT, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime;
static int count;
++count; ++count;
if (time_after(jiffies, last_msgtime + HZ)) {
last_msgtime = jiffies; /* don't report too frequently */
printk("%s: unexpected interrupt, status=0x%02x, count=%d\n", if (!time_after(jiffies, last_msgtime + HZ))
ch->name, drive->status, count); continue;
}
last_msgtime = jiffies;
printk("%s: unexpected interrupt, status=0x%02x, count=%d\n",
ch->name, drive->status, count);
} }
} }
} }
...@@ -1099,7 +963,7 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) ...@@ -1099,7 +963,7 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
unsigned long flags; unsigned long flags;
struct ata_device *drive; struct ata_device *drive;
ata_handler_t *handler; ata_handler_t *handler;
ide_startstop_t startstop; ide_startstop_t ret;
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
...@@ -1107,53 +971,53 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) ...@@ -1107,53 +971,53 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
goto out_lock; goto out_lock;
handler = ch->handler; handler = ch->handler;
if (handler == NULL || ch->poll_timeout != 0) { drive = ch->drive;
if (!handler || ch->poll_timeout) {
#if 0 #if 0
printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq); printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq);
#endif #endif
/* /*
* Not expecting an interrupt from this drive. * Not expecting an interrupt from this drive. That means this
* That means this could be: * could be:
* (1) an interrupt from another PCI device *
* sharing the same PCI INT# as us. * - an interrupt from another PCI device sharing the same PCI
* or (2) a drive just entered sleep or standby mode, * INT# as us.
* and is interrupting to let us know.
* or (3) a spurious interrupt of unknown origin.
* *
* For PCI, we cannot tell the difference, * - a drive just entered sleep or standby mode, and is
* so in that case we just ignore it and hope it goes away. * 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 #ifdef CONFIG_PCI
if (ch->pci_dev && !ch->pci_dev->vendor) if (ch->pci_dev && !ch->pci_dev->vendor)
#endif #endif
{
/* Probably not a shared PCI interrupt, so we can
* safely try to do something about it:
*/
unexpected_irq(irq); unexpected_irq(irq);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
} else { else
/* ata_status(drive, READY_STAT, BAD_STAT);
* Whack the status register, just in case we have a leftover pending IRQ.
*/
IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]);
#endif #endif
}
goto out_lock; goto out_lock;
} }
drive = ch->drive; if (!ata_status_irq(drive)) {
if (!drive_is_ready(drive)) { /* This happens regularly when we share a PCI IRQ with another device.
/*
* This happens regularly when we share a PCI IRQ with another device.
* Unfortunately, it can also happen with some buggy drives that trigger * Unfortunately, it can also happen with some buggy drives that trigger
* the IRQ before their status register is up to date. Hopefully we have * the IRQ before their status register is up to date. Hopefully we have
* enough advance overhead that the latter isn't a problem. * enough advance overhead that the latter isn't a problem.
*/ */
goto out_lock; goto out_lock;
} }
/* paranoia */ /* paranoia */
if (!test_and_set_bit(IDE_BUSY, ch->active)) 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; ch->handler = NULL;
del_timer(&ch->timer); del_timer(&ch->timer);
...@@ -1162,25 +1026,32 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) ...@@ -1162,25 +1026,32 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
if (ch->unmask) if (ch->unmask)
ide__sti(); 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); spin_lock_irq(ch->lock);
/* /*
* Note that handler() may have set things up for another * Note that handler() may have set things up for another interrupt to
* interrupt to occur soon, but it cannot happen until * occur soon, but it cannot happen until we exit from this routine,
* we exit from this routine, because it will be the * because it will be the same irq as is currently being serviced here,
* same irq as is currently being serviced here, and Linux * and Linux won't allow another of the same (on any CPU) until we
* won't allow another of the same (on any CPU) until we return. * return.
*/ */
if (startstop == ATA_OP_FINISHED) {
if (!ch->handler) { /* paranoia */ if (ret == ATA_OP_FINISHED) {
clear_bit(IDE_BUSY, ch->active);
/* Reenter the request handling engine if we are not expecting
* another interrupt.
*/
if (!ch->handler)
do_request(ch); do_request(ch);
} else { else
printk("%s: %s: huh? expected NULL handler on exit\n", drive->name, __FUNCTION__); printk("%s: %s: huh? expected NULL handler on exit\n",
} drive->name, __FUNCTION__);
} }
out_lock: out_lock:
...@@ -1202,7 +1073,7 @@ static int ide_open(struct inode * inode, struct file * filp) ...@@ -1202,7 +1073,7 @@ static int ide_open(struct inode * inode, struct file * filp)
*/ */
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
if (drive->driver == NULL) { if (!drive->driver) {
char *module = NULL; char *module = NULL;
switch (drive->type) { switch (drive->type) {
...@@ -1263,6 +1134,7 @@ static int ide_release(struct inode * inode, struct file * file) ...@@ -1263,6 +1134,7 @@ static int ide_release(struct inode * inode, struct file * file)
drive->usage--; drive->usage--;
if (ata_ops(drive) && ata_ops(drive)->release) if (ata_ops(drive) && ata_ops(drive)->release)
ata_ops(drive)->release(inode, file, drive); ata_ops(drive)->release(inode, file, drive);
return 0; return 0;
} }
...@@ -1332,7 +1204,7 @@ EXPORT_SYMBOL(ata_set_handler); ...@@ -1332,7 +1204,7 @@ EXPORT_SYMBOL(ata_set_handler);
EXPORT_SYMBOL(ata_dump); EXPORT_SYMBOL(ata_dump);
EXPORT_SYMBOL(ata_error); EXPORT_SYMBOL(ata_error);
EXPORT_SYMBOL(__ata_end_request); EXPORT_SYMBOL(ata_end_request);
EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_stall_queue);
EXPORT_SYMBOL(ide_setup_ports); EXPORT_SYMBOL(ide_setup_ports);
...@@ -140,12 +140,9 @@ struct ata_channel ide_hwifs[MAX_HWIFS]; /* master data repository */ ...@@ -140,12 +140,9 @@ struct ata_channel ide_hwifs[MAX_HWIFS]; /* master data repository */
* Setup hw_regs_t structure described by parameters. You may set up the hw * 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. * structure yourself OR use this routine to do it for you.
*/ */
void ide_setup_ports(hw_regs_t *hw, void ide_setup_ports(hw_regs_t *hw, ide_ioreg_t base, int *offsets,
ide_ioreg_t base, ide_ioreg_t ctrl, ide_ioreg_t intr,
int *offsets, int (*ack_intr)(struct ata_channel *),
ide_ioreg_t ctrl,
ide_ioreg_t intr,
ide_ack_intr_t *ack_intr,
int irq) int irq)
{ {
int i; int i;
...@@ -637,17 +634,6 @@ int ide_register_hw(hw_regs_t *hw) ...@@ -637,17 +634,6 @@ int ide_register_hw(hw_regs_t *hw)
* FIXME: rewrite the following crap: * 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(): * Parsing for ide_setup():
* *
...@@ -657,14 +643,14 @@ static int __init stridx (const char *s, char c) ...@@ -657,14 +643,14 @@ static int __init stridx (const char *s, char c)
* 3. if the remainder is a series of no more than max_vals numbers * 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 * separated by commas, the numbers are saved in vals[] and a
* count of how many were saved is returned. Base10 is assumed, * 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. * 4. otherwise, zero is returned.
*/ */
static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
{ {
static const char decimal[] = "0123456789"; int i;
static const char hex[] = "0123456789abcdef";
int i, n;
if (*s++ == '=') { if (*s++ == '=') {
/* /*
...@@ -683,23 +669,10 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m ...@@ -683,23 +669,10 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
* or base16 when prefixed with "0x". * or base16 when prefixed with "0x".
* Return a count of how many were found. * Return a count of how many were found.
*/ */
for (n = 0; (i = stridx(decimal, *s)) >= 0;) { get_options(s, max_vals+1, vals);
vals[n] = i; return vals[0];
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;
} }
return 0; /* zero = nothing matched */ return 0;
} }
/* /*
...@@ -744,7 +717,7 @@ static void __init init_global_data(void) ...@@ -744,7 +717,7 @@ static void __init init_global_data(void)
*/ */
int __init ide_setup(char *s) int __init ide_setup(char *s)
{ {
int i, vals[3]; int i, vals[4];
struct ata_channel *ch; struct ata_channel *ch;
struct ata_device *drive; struct ata_device *drive;
unsigned int hw, unit; unsigned int hw, unit;
...@@ -755,7 +728,6 @@ int __init ide_setup(char *s) ...@@ -755,7 +728,6 @@ int __init ide_setup(char *s)
return 0; return 0;
if (strncmp(s,"ide",3) && if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
strncmp(s,"hd",2)) /* hdx= & hdxlun= */ strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0; return 0;
...@@ -801,24 +773,24 @@ int __init ide_setup(char *s) ...@@ -801,24 +773,24 @@ int __init ide_setup(char *s)
unit = unit % MAX_DRIVES; unit = unit % MAX_DRIVES;
ch = &ide_hwifs[hw]; ch = &ide_hwifs[hw];
drive = &ch->drives[unit]; drive = &ch->drives[unit];
if (!strncmp(s + 4, "ide-", 4)) { if (!strncmp(s+3, "=ide-", 5)) {
strncpy(drive->driver_req, s + 4, 9); strncpy(drive->driver_req, s + 4, 9);
goto done; goto done;
} }
/* /*
* Look for last lun option: "hdxlun=" * Look for last lun option: "hdxlun="
*/ */
if (!strncmp(&s[3], "lun", 3)) { if (!strncmp(s+3, "lun=", 4)) {
if (match_parm(&s[6], NULL, vals, 1) != 1) if (*get_options(s+7, 2, vals) || vals[0]!=1)
goto bad_option; goto bad_option;
if (vals[0] >= 0 && vals[0] <= 7) { if (vals[1] >= 0 && vals[1] <= 7) {
drive->last_lun = vals[0]; drive->last_lun = vals[1];
drive->forced_lun = 1; drive->forced_lun = 1;
} else } else
printk(" -- BAD LAST LUN! Expected value from 0 to 7"); printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done; goto done;
} }
switch (match_parm(&s[3], hd_words, vals, 3)) { switch (match_parm(s+3, hd_words, vals, 3)) {
case -1: /* "none" */ case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */ drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */ case -2: /* "noprobe" */
...@@ -864,9 +836,9 @@ int __init ide_setup(char *s) ...@@ -864,9 +836,9 @@ int __init ide_setup(char *s)
#endif #endif
case 3: /* cyl,head,sect */ case 3: /* cyl,head,sect */
drive->type = ATA_DISK; drive->type = ATA_DISK;
drive->cyl = drive->bios_cyl = vals[0]; drive->cyl = drive->bios_cyl = vals[1];
drive->head = drive->bios_head = vals[1]; drive->head = drive->bios_head = vals[2];
drive->sect = drive->bios_sect = vals[2]; drive->sect = drive->bios_sect = vals[3];
drive->present = 1; drive->present = 1;
drive->forced_geom = 1; drive->forced_geom = 1;
ch->noprobe = 0; ch->noprobe = 0;
...@@ -879,10 +851,10 @@ int __init ide_setup(char *s) ...@@ -879,10 +851,10 @@ int __init ide_setup(char *s)
/* /*
* Look for bus speed option: "idebus=" * Look for bus speed option: "idebus="
*/ */
if (!strncmp(s, "idebus", 6)) { if (!strncmp(s, "idebus=", 7)) {
if (match_parm(&s[6], NULL, vals, 1) != 1) if (*get_options(s+7, 2, vals) || vals[0] != 1)
goto bad_option; goto bad_option;
idebus_parameter = vals[0]; idebus_parameter = vals[1];
goto done; goto done;
} }
...@@ -892,33 +864,72 @@ int __init ide_setup(char *s) ...@@ -892,33 +864,72 @@ int __init ide_setup(char *s)
if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) { if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
/* /*
* Be VERY CAREFUL changing this: note hardcoded indexes below * 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[] = { const char *ide_words[] = {
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
"minus8", "minus9", "minus10", "minus11",
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0'; hw = s[3] - '0';
ch = &ide_hwifs[hw]; 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); i = match_parm(&s[4], ide_words, vals, 3);
/* /*
* Cryptic check to ensure chipset not already set for a channel: * Cryptic check to ensure chipset not already set for a channel:
*/ */
if (i > 0 || i <= -11) { /* is parameter a chipset name? */ if (i) { /* is parameter a chipset name? */
if (ch->chipset != ide_unknown) if (ide_hwifs[hw].chipset != ide_unknown)
goto bad_option; /* chipset already specified */ 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 */ 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 */ goto bad_option; /* chipset for 2nd port already specified */
printk("\n"); printk("\n");
} }
switch (i) { switch (i) {
#ifdef CONFIG_BLK_DEV_PDC4030 #ifdef CONFIG_BLK_DEV_PDC4030
case -18: /* "dc4030" */ case -7: /* "dc4030" */
{ {
extern void init_pdc4030(void); extern void init_pdc4030(void);
init_pdc4030(); init_pdc4030();
...@@ -926,7 +937,7 @@ int __init ide_setup(char *s) ...@@ -926,7 +937,7 @@ int __init ide_setup(char *s)
} }
#endif #endif
#ifdef CONFIG_BLK_DEV_ALI14XX #ifdef CONFIG_BLK_DEV_ALI14XX
case -17: /* "ali14xx" */ case -6: /* "ali14xx" */
{ {
extern void init_ali14xx (void); extern void init_ali14xx (void);
init_ali14xx(); init_ali14xx();
...@@ -934,7 +945,7 @@ int __init ide_setup(char *s) ...@@ -934,7 +945,7 @@ int __init ide_setup(char *s)
} }
#endif #endif
#ifdef CONFIG_BLK_DEV_UMC8672 #ifdef CONFIG_BLK_DEV_UMC8672
case -16: /* "umc8672" */ case -5: /* "umc8672" */
{ {
extern void init_umc8672 (void); extern void init_umc8672 (void);
init_umc8672(); init_umc8672();
...@@ -942,7 +953,7 @@ int __init ide_setup(char *s) ...@@ -942,7 +953,7 @@ int __init ide_setup(char *s)
} }
#endif #endif
#ifdef CONFIG_BLK_DEV_DTC2278 #ifdef CONFIG_BLK_DEV_DTC2278
case -15: /* "dtc2278" */ case -4: /* "dtc2278" */
{ {
extern void init_dtc2278 (void); extern void init_dtc2278 (void);
init_dtc2278(); init_dtc2278();
...@@ -950,7 +961,7 @@ int __init ide_setup(char *s) ...@@ -950,7 +961,7 @@ int __init ide_setup(char *s)
} }
#endif #endif
#ifdef CONFIG_BLK_DEV_CMD640 #ifdef CONFIG_BLK_DEV_CMD640
case -14: /* "cmd640_vlb" */ case -3: /* "cmd640_vlb" */
{ {
extern int cmd640_vlb; /* flag for cmd640.c */ extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1; cmd640_vlb = 1;
...@@ -958,7 +969,7 @@ int __init ide_setup(char *s) ...@@ -958,7 +969,7 @@ int __init ide_setup(char *s)
} }
#endif #endif
#ifdef CONFIG_BLK_DEV_HT6560B #ifdef CONFIG_BLK_DEV_HT6560B
case -13: /* "ht6560b" */ case -2: /* "ht6560b" */
{ {
extern void init_ht6560b (void); extern void init_ht6560b (void);
init_ht6560b(); init_ht6560b();
...@@ -966,64 +977,22 @@ int __init ide_setup(char *s) ...@@ -966,64 +977,22 @@ int __init ide_setup(char *s)
} }
#endif #endif
#if CONFIG_BLK_DEV_QD65XX #if CONFIG_BLK_DEV_QD65XX
case -12: /* "qd65xx" */ case -1: /* "qd65xx" */
{ {
extern void init_qd65xx (void); extern void init_qd65xx (void);
init_qd65xx(); init_qd65xx();
goto done; goto done;
} }
#endif #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 */ case 1: /* base */
vals[1] = vals[0] + 0x206; /* default ctl */ vals[2] = vals[1] + 0x206; /* default ctl */
case 2: /* base,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 */ case 3: /* base,ctl,irq */
ch->hw.irq = vals[2]; ch->hw.irq = vals[3];
ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &ch->irq); 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)); memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
ch->irq = vals[2]; ch->irq = vals[3];
ch->noprobe = 0; ch->noprobe = 0;
ch->chipset = ide_generic; ch->chipset = ide_generic;
goto done; goto done;
......
...@@ -46,7 +46,7 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq) ...@@ -46,7 +46,7 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
if (!dma_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; return ATA_OP_FINISHED;
} }
...@@ -510,7 +510,7 @@ int udma_pci_irq_status(struct ata_device *drive) ...@@ -510,7 +510,7 @@ int udma_pci_irq_status(struct ata_device *drive)
void udma_pci_timeout(struct ata_device *drive) 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) void udma_pci_irq_lost(struct ata_device *drive)
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
* linux/drivers/ide/pdc202xx.c Version 0.30 May. 28, 2002 * linux/drivers/ide/pdc202xx.c Version 0.30 May. 28, 2002
* *
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * 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. * Portions Copyright (C) 1999-2002 Promise Technology, Inc.
* Author: Frank Tiernan (frankt@promise.com) * 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 * May be copied or modified under the terms of the GNU General Public License
* *
...@@ -22,11 +23,21 @@ ...@@ -22,11 +23,21 @@
* *
* The latest chipset code will support the following :: * The latest chipset code will support the following ::
* Three Ultra33 controllers and 12 drives. * Three Ultra33 controllers and 12 drives.
*
* 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. * 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. * The 8/4 ratio is a BIOS code limit by promise.
* *
* UNLESS you enable "CONFIG_PDC202XX_BURST" * 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> #include <linux/config.h>
...@@ -108,6 +119,8 @@ static void pdc_dump_bits(struct pdc_bit_messages *msgs, byte bits) ...@@ -108,6 +119,8 @@ static void pdc_dump_bits(struct pdc_bit_messages *msgs, byte bits)
} }
#endif /* PDC202XX_DECODE_REGISTER_INFO */ #endif /* PDC202XX_DECODE_REGISTER_INFO */
static struct ata_device* drives[4];
int check_in_drive_lists(struct ata_device *drive) int check_in_drive_lists(struct ata_device *drive)
{ {
static const char *pdc_quirk_drives[] = { static const char *pdc_quirk_drives[] = {
...@@ -115,12 +128,14 @@ int check_in_drive_lists(struct ata_device *drive) ...@@ -115,12 +128,14 @@ int check_in_drive_lists(struct ata_device *drive)
"QUANTUM FIREBALLP KA6.4", "QUANTUM FIREBALLP KA6.4",
"QUANTUM FIREBALLP KA9.1", "QUANTUM FIREBALLP KA9.1",
"QUANTUM FIREBALLP LM20.4", "QUANTUM FIREBALLP LM20.4",
"QUANTUM FIREBALLP KX13.6",
"QUANTUM FIREBALLP KX20.5", "QUANTUM FIREBALLP KX20.5",
"QUANTUM FIREBALLP KX27.3", "QUANTUM FIREBALLP KX27.3",
"QUANTUM FIREBALLP LM20.5", "QUANTUM FIREBALLP LM20.5",
NULL NULL
}; };
const char**list = pdc_quirk_drives;
const char**list = pdc_quirk_drives;
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
while (*list) while (*list)
...@@ -136,6 +151,7 @@ static int __init pdc202xx_modes_map(struct ata_channel *ch) ...@@ -136,6 +151,7 @@ static int __init pdc202xx_modes_map(struct ata_channel *ch)
switch(ch->pci_dev->device) { switch(ch->pci_dev->device) {
case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20275: case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20271:
case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20269:
map |= XFER_UDMA_133; map |= XFER_UDMA_133;
case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268R:
...@@ -250,105 +266,125 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed) ...@@ -250,105 +266,125 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed)
static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed) static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
{ {
struct ata_channel *hwif = drive->channel; 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); u32 high_16 = pci_resource_start(hwif->pci_dev, 4);
unsigned long indexreg = high_16 + (hwif->unit ? 0x09 : 0x01); u32 indexreg = high_16 + (hwif->unit ? 0x09 : 0x01);
unsigned long datareg = (indexreg + 2); u32 datareg = indexreg + 2;
#endif /* CONFIG_BLK_DEV_IDEDMA */
byte thold = 0x10; u8 adj = (drive->dn % 2) ? 0x08 : 0x00;
byte adj = (drive->dn%2) ? 0x08 : 0x00; u8 thold = 0x10;
int err, i, j = hwif->unit ? 2 : 0;
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
/* Setting tHOLD bit to 0 if using UDMA mode 2 */
if (speed == XFER_UDMA_2) { if (speed == XFER_UDMA_2) {
OUT_BYTE((thold + adj), indexreg); OUT_BYTE((thold + adj), indexreg);
OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg); OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg);
} }
switch (speed) { #endif
case XFER_UDMA_7:
speed = XFER_UDMA_6; for (i = 0 ; i < 2 ; i++)
case XFER_UDMA_6: if (hwif->drives[i].present)
set_2regs(0x10, 0x1a); drives[i+j] = &hwif->drives[i];
set_2regs(0x11, 0x01);
set_2regs(0x12, 0xcb); err = ide_config_drive_speed(drive, speed);
break;
case XFER_UDMA_5: /* For modes < UDMA mode 6 we need only to SET_FEATURE */
set_2regs(0x10, 0x1a); if (speed < XFER_UDMA_6)
set_2regs(0x11, 0x02); return err;
set_2regs(0x12, 0xcb);
break; /* We need to adjust timings to ATA133 clock if ATA133 drives exist */
case XFER_UDMA_4: for (i = 0 ; i < 4 ; i++) {
set_2regs(0x10, 0x1a); if (!drives[i])
set_2regs(0x11, 0x03); continue;
set_2regs(0x12, 0xcd);
break; /* Primary = 0x01, Secondary = 0x09 */
case XFER_UDMA_3: indexreg = high_16 + ((i > 1) ? 0x09 : 0x01);
set_2regs(0x10, 0x1a); datareg = indexreg + 2;
set_2regs(0x11, 0x05);
set_2regs(0x12, 0xcd); /* Master = 0x00, Slave = 0x08 */
break; adj = (i % 2) ? 0x08 : 0x00;
case XFER_UDMA_2:
set_2regs(0x10, 0x2a); switch (drives[i]->current_speed) {
set_2regs(0x11, 0x07); #ifdef CONFIG_BLK_DEV_IDEDMA
set_2regs(0x12, 0xcd); case XFER_UDMA_6:
break; set_2regs(0x10, 0x1a);
case XFER_UDMA_1: set_2regs(0x11, 0x01);
set_2regs(0x10, 0x3a); set_2regs(0x12, 0xcb);
set_2regs(0x11, 0x0a); break;
set_2regs(0x12, 0xd0); case XFER_UDMA_5:
break; set_2regs(0x10, 0x1a);
case XFER_UDMA_0: set_2regs(0x11, 0x02);
set_2regs(0x10, 0x4a); set_2regs(0x12, 0xcb);
set_2regs(0x11, 0x0f); break;
set_2regs(0x12, 0xd5); case XFER_UDMA_4:
break; set_2regs(0x10, 0x1a);
case XFER_MW_DMA_2: set_2regs(0x11, 0x03);
set_2regs(0x0e, 0x69); set_2regs(0x12, 0xcd);
set_2regs(0x0f, 0x25); break;
break; case XFER_UDMA_3:
case XFER_MW_DMA_1: set_2regs(0x10, 0x1a);
set_2regs(0x0e, 0x6b); set_2regs(0x11, 0x05);
set_2regs(0x0f, 0x27); set_2regs(0x12, 0xcd);
break; break;
case XFER_MW_DMA_0: case XFER_UDMA_2:
set_2regs(0x0e, 0xdf); set_2regs(0x10, 0x2a);
set_2regs(0x0f, 0x5f); set_2regs(0x11, 0x07);
break; set_2regs(0x12, 0xcd);
#else break;
switch (speed) { case XFER_UDMA_1:
#endif /* CONFIG_BLK_DEV_IDEDMA */ set_2regs(0x10, 0x3a);
case XFER_PIO_4: set_2regs(0x11, 0x0a);
set_2regs(0x0c, 0x23); set_2regs(0x12, 0xd0);
set_2regs(0x0d, 0x09); break;
set_2regs(0x13, 0x25); case XFER_UDMA_0:
break; set_2regs(0x10, 0x4a);
case XFER_PIO_3: set_2regs(0x11, 0x0f);
set_2regs(0x0c, 0x27); set_2regs(0x12, 0xd5);
set_2regs(0x0d, 0x0d); break;
set_2regs(0x13, 0x35); case XFER_MW_DMA_2:
break; set_2regs(0x0e, 0x69);
case XFER_PIO_2: set_2regs(0x0f, 0x25);
set_2regs(0x0c, 0x23); break;
set_2regs(0x0d, 0x26); case XFER_MW_DMA_1:
set_2regs(0x13, 0x64); set_2regs(0x0e, 0x6b);
break; set_2regs(0x0f, 0x27);
case XFER_PIO_1: break;
set_2regs(0x0c, 0x46); case XFER_MW_DMA_0:
set_2regs(0x0d, 0x29); set_2regs(0x0e, 0xdf);
set_2regs(0x13, 0xa4); set_2regs(0x0f, 0x5f);
break; break;
case XFER_PIO_0: #endif
set_2regs(0x0c, 0xfb); case XFER_PIO_4:
set_2regs(0x0d, 0x2b); set_2regs(0x0c, 0x23);
set_2regs(0x13, 0xac); set_2regs(0x0d, 0x09);
break; set_2regs(0x13, 0x25);
default: 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 /* 0 1 2 3 4 5 6 7 8
...@@ -475,16 +511,19 @@ static void pdc202xx_udma_start(struct ata_device *drive, struct request *rq) ...@@ -475,16 +511,19 @@ static void pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4); 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) { if (drive->addressing) {
unsigned long word_count = 0; unsigned long word_count = 0, hankval;
u8 clock = IN_BYTE(high_16 + PDC_CLK); 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->nr_sectors << 8);
word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000; hankval = (rq_data_dir(rq) == READ) ? 0x05 << 24 : 0x06 << 24;
outl(word_count, atapi_reg); hankval |= word_count;
outl(hankval, atapi_port);
} }
/* Note that this is done *after* the cmd has been issued to the drive, /* Note that this is done *after* the cmd has been issued to the drive,
...@@ -499,14 +538,18 @@ static int pdc202xx_udma_stop(struct ata_device *drive) ...@@ -499,14 +538,18 @@ static int pdc202xx_udma_stop(struct ata_device *drive)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4); 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; 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) { if (drive->addressing) {
outl(0, atapi_reg); /* zero out extra */ u32 clockreg = high_16 + PDC_CLK;
clock = IN_BYTE(high_16 + PDC_CLK); u8 clock;
OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + PDC_CLK);
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 */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
...@@ -527,21 +570,21 @@ static void pdc202xx_bug(struct ata_device *drive) ...@@ -527,21 +570,21 @@ static void pdc202xx_bug(struct ata_device *drive)
#endif #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); outb(0x04, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
mdelay(1000); udelay(10);
ata_irq_enable(drive, 1); outb(0x00, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
mdelay(1000);
printk(KERN_INFO "PDC202XX: %s channel reset.\n", printk(KERN_INFO "PDC202XX: %s channel reset.\n",
drive->channel->unit ? "Secondary" : "Primary"); drive->channel->unit ? "Secondary" : "Primary");
} }
/* /*
* software host reset * software host reset
* *
* BIOS will set UDMA timing on if the drive supports it. * 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 * that device cannot handle a downgrade in timing from
* UDMA to DMA. Disk accesses after issuing a set * UDMA to DMA. Disk accesses after issuing a set
* feature command will result in errors. * feature command will result in errors.
...@@ -549,6 +592,7 @@ static void pdc202xx_new_reset(struct ata_device *drive) ...@@ -549,6 +592,7 @@ static void pdc202xx_new_reset(struct ata_device *drive)
* A software reset leaves the timing registers intact, * A software reset leaves the timing registers intact,
* but resets the drives on both channels. * but resets the drives on both channels.
*/ */
#if 0
static void pdc202xx_reset_host(struct pci_dev *dev) static void pdc202xx_reset_host(struct pci_dev *dev)
{ {
u32 high_16 = pci_resource_start(dev, 4); u32 high_16 = pci_resource_start(dev, 4);
...@@ -566,17 +610,24 @@ void pdc202xx_reset(struct ata_device *drive) ...@@ -566,17 +610,24 @@ void pdc202xx_reset(struct ata_device *drive)
printk(KERN_INFO "%s: channel needs reset.\n", ch->name); printk(KERN_INFO "%s: channel needs reset.\n", ch->name);
pdc202xx_reset_host(ch->pci_dev); pdc202xx_reset_host(ch->pci_dev);
} }
#endif
static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
{ {
u32 high_16 = pci_resource_start(dev, 4); 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) { 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); 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); printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start);
} }
#if 0
switch (dev->device) { switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265: case PCI_DEVICE_ID_PROMISE_20265:
...@@ -584,8 +635,6 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) ...@@ -584,8 +635,6 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
pdc202xx_reset_host(dev); pdc202xx_reset_host(dev);
break; break;
default: 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) { if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
byte irq = 0, irq2 = 0; byte irq = 0, irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
...@@ -597,11 +646,13 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) ...@@ -597,11 +646,13 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
} }
break; break;
} }
#endif
#ifdef CONFIG_PDC202XX_BURST #ifdef CONFIG_PDC202XX_BURST
if (!(burst & 1)) { if (!(burst & 1)) {
printk(KERN_INFO "%s: forcing (U)DMA BURST.\n", dev->name); 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 #endif
printk(KERN_INFO "%s: (U)DMA BURST %sabled, " printk(KERN_INFO "%s: (U)DMA BURST %sabled, "
...@@ -613,6 +664,7 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) ...@@ -613,6 +664,7 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
return dev->irq; return dev->irq;
} }
#if 0
/* chipsets newer then 20267 */ /* chipsets newer then 20267 */
static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev) static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev)
{ {
...@@ -622,6 +674,7 @@ static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev) ...@@ -622,6 +674,7 @@ static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev)
} }
return dev->irq; return dev->irq;
} }
#endif
static unsigned int __init pdc202xx_ata66_check(struct ata_channel *ch) static unsigned int __init pdc202xx_ata66_check(struct ata_channel *ch)
{ {
...@@ -642,17 +695,18 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif) ...@@ -642,17 +695,18 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
{ {
hwif->tuneproc = &pdc202xx_tune_drive; hwif->tuneproc = &pdc202xx_tune_drive;
hwif->quirkproc = &check_in_drive_lists; hwif->quirkproc = &check_in_drive_lists;
hwif->resetproc = &pdc202xx_reset;
switch(hwif->pci_dev->device) { switch(hwif->pci_dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20276: 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_20269:
case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20268:
case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268R:
hwif->udma_four = pdc202xx_tx_ata66_check(hwif); hwif->udma_four = pdc202xx_tx_ata66_check(hwif);
hwif->speedproc = &pdc202xx_new_tune_chipset; hwif->speedproc = &pdc202xx_new_tune_chipset;
hwif->resetproc = &pdc202xx_new_reset;
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) if (hwif->dma_base)
hwif->udma_setup = pdc202xx_tx_udma_setup; hwif->udma_setup = pdc202xx_tx_udma_setup;
...@@ -660,10 +714,6 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif) ...@@ -660,10 +714,6 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
break; break;
case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265: 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 #ifdef CONFIG_BLK_DEV_IDEDMA
/* we need special functions for lba48 */ /* we need special functions for lba48 */
if (hwif->dma_base) { if (hwif->dma_base) {
...@@ -671,7 +721,10 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif) ...@@ -671,7 +721,10 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
hwif->udma_stop = pdc202xx_udma_stop; hwif->udma_stop = pdc202xx_udma_stop;
} }
#endif #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: case PCI_DEVICE_ID_PROMISE_20246:
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) if (hwif->dma_base)
...@@ -752,7 +805,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -752,7 +805,7 @@ static struct ata_pci_device chipsets[] __initdata = {
{ {
vendor: PCI_VENDOR_ID_PROMISE, vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20268, device: PCI_DEVICE_ID_PROMISE_20268,
init_chipset: pdc202xx_tx_init_chipset, init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx, init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
...@@ -764,7 +817,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -764,7 +817,7 @@ static struct ata_pci_device chipsets[] __initdata = {
{ {
vendor: PCI_VENDOR_ID_PROMISE, vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20268R, device: PCI_DEVICE_ID_PROMISE_20268R,
init_chipset: pdc202xx_tx_init_chipset, init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx, init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
...@@ -772,7 +825,15 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -772,7 +825,15 @@ static struct ata_pci_device chipsets[] __initdata = {
{ {
vendor: PCI_VENDOR_ID_PROMISE, vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20269, 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, init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
...@@ -780,7 +841,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -780,7 +841,7 @@ static struct ata_pci_device chipsets[] __initdata = {
{ {
vendor: PCI_VENDOR_ID_PROMISE, vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20275, device: PCI_DEVICE_ID_PROMISE_20275,
init_chipset: pdc202xx_tx_init_chipset, init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx, init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
...@@ -788,7 +849,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -788,7 +849,7 @@ static struct ata_pci_device chipsets[] __initdata = {
{ {
vendor: PCI_VENDOR_ID_PROMISE, vendor: PCI_VENDOR_ID_PROMISE,
device: PCI_DEVICE_ID_PROMISE_20276, device: PCI_DEVICE_ID_PROMISE_20276,
init_chipset: pdc202xx_tx_init_chipset, init_chipset: pdc202xx_init_chipset,
init_channel: ide_init_pdc202xx, init_channel: ide_init_pdc202xx,
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
......
...@@ -415,7 +415,7 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -415,7 +415,7 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
rq->nr_sectors -= nsect; rq->nr_sectors -= nsect;
total_remaining = rq->nr_sectors; total_remaining = rq->nr_sectors;
if ((rq->current_nr_sectors -= nsect) <= 0) 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: * Now the data has been read in, do the following:
...@@ -477,7 +477,7 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc ...@@ -477,7 +477,7 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif #endif
__ata_end_request(drive, rq, 1, rq->nr_sectors); ata_end_request(drive, rq, 1, rq->nr_sectors);
return ATA_OP_FINISHED; return ATA_OP_FINISHED;
} }
...@@ -629,7 +629,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -629,7 +629,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
/* Check that it's a regular command. If not, bomb out early. */ /* Check that it's a regular command. If not, bomb out early. */
if (!(rq->flags & REQ_CMD)) { if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "pdc4030 bad flags"); 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; return ATA_OP_FINISHED;
} }
...@@ -709,7 +709,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -709,7 +709,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
default: default:
printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n"); 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; return ATA_OP_FINISHED;
} }
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
Authors: Arjan van de Ven <arjanv@redhat.com> Authors: Arjan van de Ven <arjanv@redhat.com>
Based on work done by Sren Schmidt for FreeBSD Based on work done by Søren Schmidt for FreeBSD
*/ */
......
...@@ -97,11 +97,15 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg) ...@@ -97,11 +97,15 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg)
} }
} }
/* There used to be code here that assigned drive->id->CHS /* There used to be code here that assigned drive->id->CHS to
to drive->CHS and that to drive->bios_CHS. However, some disks have * 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 * 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 * that code was wrong. Moreover, there seems to be no reason to do
any of these things. */ * any of these things.
*
* Please note that recent RedHat changes to the disk utils are bogous
* and will report spurious errors.
*/
/* translate? */ /* translate? */
if (drive->forced_geom) if (drive->forced_geom)
...@@ -169,8 +173,8 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg) ...@@ -169,8 +173,8 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg)
} }
/* /*
* hd_driveid data come as little endian, it needs to be converted on big * Drive ID data come as little endian, it needs to be converted on big endian
* endian machines. * machines.
*/ */
void ata_fix_driveid(struct hd_driveid *id) void ata_fix_driveid(struct hd_driveid *id)
{ {
...@@ -319,11 +323,8 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed) ...@@ -319,11 +323,8 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2);
#endif #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 * Select the drive, and issue the SETFEATURES command.
* (lost interrupt).
*
* Select the drive, and issue the SETFEATURES command
*/ */
disable_irq(ch->irq); /* disable_irq_nosync ?? */ disable_irq(ch->irq); /* disable_irq_nosync ?? */
udelay(1); udelay(1);
...@@ -339,7 +340,6 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed) ...@@ -339,7 +340,6 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
udelay(1); udelay(1);
ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_CMD, NULL); ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_CMD, NULL);
ata_mask(drive); ata_mask(drive);
enable_irq(ch->irq); enable_irq(ch->irq);
if (ret != ATA_OP_READY) { if (ret != ATA_OP_READY) {
...@@ -1127,6 +1127,7 @@ static void channel_init(struct ata_channel *ch) ...@@ -1127,6 +1127,7 @@ static void channel_init(struct ata_channel *ch)
gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL); gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL);
if (!gd->sizes) if (!gd->sizes)
goto err_kmalloc_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); gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
if (!gd->part) if (!gd->part)
......
...@@ -134,7 +134,6 @@ static void tcq_invalidate_queue(struct ata_device *drive) ...@@ -134,7 +134,6 @@ static void tcq_invalidate_queue(struct ata_device *drive)
ar->XXX_handler = tcq_nop_handler; ar->XXX_handler = tcq_nop_handler;
ar->command_type = IDE_DRIVE_TASK_NO_DATA; 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); _elv_add_request(q, rq, 0, 0);
out: out:
...@@ -359,7 +358,7 @@ static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *r ...@@ -359,7 +358,7 @@ static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *r
TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag); 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 * we completed this command, check if we can service a new command
......
...@@ -129,7 +129,7 @@ void __init init_umc8672(void) /* called from ide.c */ ...@@ -129,7 +129,7 @@ void __init init_umc8672(void) /* called from ide.c */
__save_flags(flags); /* local CPU only */ __save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */ __cli(); /* local CPU only */
if (check_region(0x108, 2)) { if (!request_region(0x108, 2, "umc8672")) {
__restore_flags(flags); __restore_flags(flags);
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return; return;
...@@ -138,6 +138,7 @@ void __init init_umc8672(void) /* called from ide.c */ ...@@ -138,6 +138,7 @@ void __init init_umc8672(void) /* called from ide.c */
if (in_umc (0xd5) != 0xa0) if (in_umc (0xd5) != 0xa0)
{ {
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
release_region(0x108, 2);
printk ("umc8672: not found\n"); printk ("umc8672: not found\n");
return; return;
} }
...@@ -146,7 +147,6 @@ void __init init_umc8672(void) /* called from ide.c */ ...@@ -146,7 +147,6 @@ void __init init_umc8672(void) /* called from ide.c */
umc_set_speeds (current_speeds); umc_set_speeds (current_speeds);
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
request_region(0x108, 2, "umc8672");
ide_hwifs[0].chipset = ide_umc8672; ide_hwifs[0].chipset = ide_umc8672;
ide_hwifs[1].chipset = ide_umc8672; ide_hwifs[1].chipset = ide_umc8672;
ide_hwifs[0].tuneproc = &tune_umc; ide_hwifs[0].tuneproc = &tune_umc;
......
...@@ -244,7 +244,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int ...@@ -244,7 +244,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int
u8 *scsi_buf; u8 *scsi_buf;
if (!(rq->flags & REQ_PC)) { if (!(rq->flags & REQ_PC)) {
__ata_end_request(drive, rq, uptodate, 0); ata_end_request(drive, rq, uptodate, 0);
return 0; return 0;
} }
...@@ -491,14 +491,13 @@ static void idescsi_release(struct inode *inode, struct file *filp, struct ata_d ...@@ -491,14 +491,13 @@ static void idescsi_release(struct inode *inode, struct file *filp, struct ata_d
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
static Scsi_Host_Template template;
static int idescsi_cleanup (struct ata_device *drive) static int idescsi_cleanup (struct ata_device *drive)
{ {
struct Scsi_Host *host = drive->driver_data;
if (ide_unregister_subdriver (drive)) { if (ide_unregister_subdriver (drive)) {
return 1; return 1;
} }
scsi_unregister(host); scsi_unregister_host(&template);
return 0; return 0;
} }
...@@ -801,7 +800,6 @@ static int __init init_idescsi_module(void) ...@@ -801,7 +800,6 @@ static int __init init_idescsi_module(void)
static void __exit exit_idescsi_module(void) static void __exit exit_idescsi_module(void)
{ {
unregister_ata_driver(&ata_ops); unregister_ata_driver(&ata_ops);
scsi_unregister_host(&template);
} }
module_init(init_idescsi_module); module_init(init_idescsi_module);
......
...@@ -74,15 +74,6 @@ struct atapi_packet_command { ...@@ -74,15 +74,6 @@ struct atapi_packet_command {
} s; } 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. * ATAPI Status Register.
*/ */
...@@ -360,3 +351,20 @@ typedef struct atapi_request_sense { ...@@ -360,3 +351,20 @@ typedef struct atapi_request_sense {
u8 sk_specific[2]; /* Sense Key Specific */ u8 sk_specific[2]; /* Sense Key Specific */
u8 pad[2]; /* Padding to 20 bytes */ u8 pad[2]; /* Padding to 20 bytes */
} atapi_request_sense_result_t; } 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 #ifndef _IDE_H
#define _IDE_H #define _IDE_H
/* /*
* Copyright (C) 1994-2002 Linus Torvalds & authors * Copyright (C) 1994-2002 Linus Torvalds & authors
*/ */
...@@ -57,15 +58,14 @@ typedef unsigned char byte; /* used everywhere */ ...@@ -57,15 +58,14 @@ typedef unsigned char byte; /* used everywhere */
*/ */
#define ERROR_MAX 8 /* Max read/write errors per sector */ #define ERROR_MAX 8 /* Max read/write errors per sector */
#define ERROR_RESET 3 /* Reset controller every 4th retry */ #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 */ #define DMA_PIO_RETRY 1 /* retrying in PIO */
/* /*
* Definitions for accessing IDE controller registers * Definitions for accessing IDE controller registers.
*/ */
enum { enum {
...@@ -192,23 +192,21 @@ typedef enum { ...@@ -192,23 +192,21 @@ typedef enum {
* Structure to hold all information about the location of this port * Structure to hold all information about the location of this port
*/ */
typedef struct hw_regs_s { typedef struct hw_regs_s {
ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */ ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
int irq; /* our irq number */ int irq; /* our irq number */
int dma; /* our dma entry */ int dma; /* our dma entry */
ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ int (*ack_intr)(struct ata_channel *); /* acknowledge interrupt */
hwif_chipset_t chipset; hwif_chipset_t chipset;
} hw_regs_t; } hw_regs_t;
/* /*
* Set up hw_regs_t structure before calling ide_register_hw (optional) * Set up hw_regs_t structure before calling ide_register_hw (optional)
*/ */
void ide_setup_ports(hw_regs_t *hw, extern void ide_setup_ports(hw_regs_t *hw,
ide_ioreg_t base, ide_ioreg_t base, int *offsets,
int *offsets, ide_ioreg_t ctrl, ide_ioreg_t intr,
ide_ioreg_t ctrl, int (*ack_intr)(struct ata_channel *),
ide_ioreg_t intr, int irq);
ide_ack_intr_t *ack_intr,
int irq);
#include <asm/ide.h> #include <asm/ide.h>
...@@ -282,14 +280,10 @@ struct ata_device { ...@@ -282,14 +280,10 @@ struct ata_device {
unsigned int usage; /* current "open()" count for drive */ unsigned int usage; /* current "open()" count for drive */
char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */ char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */
/* NOTE: If we had proper separation between channel and host chip, we request_queue_t queue; /* per device request queue */
* could move this to the channel and many sync problems would
* magically just go away.
*/
request_queue_t queue; /* per device request queue */
struct request *rq; /* current request */ 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 retry_pio; /* retrying dma capable host in pio */
byte state; /* retry state */ byte state; /* retry state */
...@@ -341,6 +335,7 @@ struct ata_device { ...@@ -341,6 +335,7 @@ struct ata_device {
void *driver_data; /* extra driver data */ void *driver_data; /* extra driver data */
devfs_handle_t de; /* directory for device */ devfs_handle_t de; /* directory for device */
char driver_req[10]; /* requests specific driver */ char driver_req[10]; /* requests specific driver */
int last_lun; /* last logical unit */ int last_lun; /* last logical unit */
...@@ -392,6 +387,7 @@ enum { ...@@ -392,6 +387,7 @@ enum {
enum { enum {
IDE_BUSY, /* awaiting an interrupt */ IDE_BUSY, /* awaiting an interrupt */
IDE_SLEEP, IDE_SLEEP,
IDE_PIO, /* PIO in progress */
IDE_DMA /* DMA in progress */ IDE_DMA /* DMA in progress */
}; };
...@@ -404,11 +400,15 @@ struct ata_channel { ...@@ -404,11 +400,15 @@ struct ata_channel {
*/ */
spinlock_t *lock; spinlock_t *lock;
unsigned long *active; /* active processing request */ unsigned long *active; /* active processing request */
ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */ 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 */ struct timer_list timer; /* failsafe timer */
ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *); /* irq handler, if active */ ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *); /* irq handler, if active */
unsigned long poll_timeout; /* timeout value during polled operations */ unsigned long poll_timeout; /* timeout value during polled operations */
struct ata_device *drive; /* last serviced drive */ struct ata_device *drive; /* last serviced drive */
...@@ -508,8 +508,6 @@ struct ata_channel { ...@@ -508,8 +508,6 @@ struct ata_channel {
extern int ide_register_hw(hw_regs_t *hw); extern int ide_register_hw(hw_regs_t *hw);
extern void ide_unregister(struct ata_channel *); extern void ide_unregister(struct ata_channel *);
struct ata_taskfile;
#define IDE_MAX_TAG 32 #define IDE_MAX_TAG 32
#ifdef CONFIG_BLK_DEV_IDE_TCQ #ifdef CONFIG_BLK_DEV_IDE_TCQ
...@@ -605,8 +603,7 @@ extern int noautodma; ...@@ -605,8 +603,7 @@ extern int noautodma;
#define DEVICE_NR(device) (minor(device) >> PARTN_BITS) #define DEVICE_NR(device) (minor(device) >> PARTN_BITS)
#include <linux/blk.h> #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, extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
unsigned long timeout, ata_expiry_t expiry); unsigned long timeout, ata_expiry_t expiry);
...@@ -626,22 +623,11 @@ int ide_xlate_1024(kdev_t, int, int, const char *); ...@@ -626,22 +623,11 @@ int ide_xlate_1024(kdev_t, int, int, const char *);
*/ */
struct ata_device *get_info_ptr(kdev_t i_rdev); 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 * temporarily mapping a (possible) highmem bio for PIO transfer
*/ */
#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) #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 ata_taskfile {
struct hd_drive_task_hdr taskfile; struct hd_drive_task_hdr taskfile;
struct hd_drive_task_hdr hobfile; struct hd_drive_task_hdr hobfile;
...@@ -654,7 +640,6 @@ extern void ata_read(struct ata_device *, void *, unsigned int); ...@@ -654,7 +640,6 @@ extern void ata_read(struct ata_device *, void *, unsigned int);
extern void ata_write(struct ata_device *, void *, unsigned int); extern void ata_write(struct ata_device *, void *, unsigned int);
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *); 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 int ide_config_drive_speed(struct ata_device *, byte);
extern byte eighty_ninty_three(struct ata_device *); extern byte eighty_ninty_three(struct ata_device *);
...@@ -803,13 +788,12 @@ extern spinlock_t ide_lock; ...@@ -803,13 +788,12 @@ extern spinlock_t ide_lock;
#define DRIVE_LOCK(drive) ((drive)->queue.queue_lock) #define DRIVE_LOCK(drive) ((drive)->queue.queue_lock)
extern int drive_is_ready(struct ata_device *drive);
/* Low level device access functions. */ /* Low level device access functions. */
extern void ata_select(struct ata_device *, unsigned long); extern void ata_select(struct ata_device *, unsigned long);
extern void ata_mask(struct ata_device *); extern void ata_mask(struct ata_device *);
extern int ata_status(struct ata_device *, u8, u8); 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, extern int ata_status_poll( struct ata_device *, u8, u8,
unsigned long, struct request *rq); unsigned long, struct request *rq);
......
...@@ -610,6 +610,7 @@ ...@@ -610,6 +610,7 @@
#define PCI_DEVICE_ID_PROMISE_20268 0x4d68 #define PCI_DEVICE_ID_PROMISE_20268 0x4d68
#define PCI_DEVICE_ID_PROMISE_20268R 0x6268 #define PCI_DEVICE_ID_PROMISE_20268R 0x6268
#define PCI_DEVICE_ID_PROMISE_20269 0x4d69 #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_20275 0x1275
#define PCI_DEVICE_ID_PROMISE_20276 0x5275 #define PCI_DEVICE_ID_PROMISE_20276 0x5275
#define PCI_DEVICE_ID_PROMISE_5300 0x5300 #define PCI_DEVICE_ID_PROMISE_5300 0x5300
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment