Commit 467b45ea authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.20 IDE 86

Most importantly this makes ide-scsi work again, which I broke
IDE 85. And we are starting to be serious about locking issues.
However the locking issues will take some patches until they stabilize.

 - Add spin locks in ata_special_intr.

 - Add Server Works CSB6 handling by Matt Domsch.

 - Atari updates by Geert Uytterhoeven:
   * irq_lock is used in more than one file, so make it global and rename it
     to ide_irq_lock
   * `hwgroup' is dead, use `channel' instead
   * ide_irq_lock depends on ATA_ARCH_LOCK, not on m68k or APUS

 - Small janitorial tidbits by Angus Sawyer.

 - PIIX driver updates by Vojtech Pavlik:

   * Removes the CONFIG_BLK_DEV_PIIX_TRY133 option. I've got an official
     statement from Intel saying that the controller definitely isn't intended
     to operate at this speed and doing so may cause severe trouble.

   * Fixes a bug in ata-timing.c, where EIDE timing data was discarded by
     accident.

   * Fixed a couple bugs in the Artop driver (UDMA clocks, active/recovery
     timing), 8-bit timing merging.

   * Removes an unused variable from piix.c

 - Move locking out from ide_set_handler(). There are places where it incurred
   too frequent lock grab and release or where we did miss to lock against
   concurrent hardware access.

   Generally the locking appears to be too fine grained and inconsistent at many
   places. This is the first cut. We will deal with it step by step.

 - Make sure message string is initialized even if FANCY_STATUS_DUMPS is
   disabled.

 - Don't lock directly inside udma_init and implementations of this method.

 - Guard against REQ_SPECIAL issued by the SCSI layer on us. Use REQ_PC in
   ide-scsi.c instead.
parent 71e3ff68
...@@ -791,7 +791,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct ...@@ -791,7 +791,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
if(!atapi) { if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */ /* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */ /* issue cmd to drive */
OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG); OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG);
...@@ -802,10 +802,10 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct ...@@ -802,10 +802,10 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
*R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
/* initiate a multi word dma read using DMA handshaking */ /* initiate a multi word dma read using DMA handshaking */
*R_ATA_TRANSFER_CNT = *R_ATA_TRANSFER_CNT =
IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
*R_ATA_CTRL_DATA = *R_ATA_CTRL_DATA =
IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
IO_STATE(R_ATA_CTRL_DATA, rw, read) | IO_STATE(R_ATA_CTRL_DATA, rw, read) |
...@@ -831,7 +831,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct ...@@ -831,7 +831,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
if(!atapi) { if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */ /* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */ /* issue cmd to drive */
OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG); OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG);
......
...@@ -408,16 +408,6 @@ CONFIG_BLK_DEV_PIIX ...@@ -408,16 +408,6 @@ CONFIG_BLK_DEV_PIIX
the kernel to change PIO, DMA and UDMA speeds and to configure the kernel to change PIO, DMA and UDMA speeds and to configure
the chip to optimum performance. the chip to optimum performance.
CONFIG_BLK_DEV_PIIX_TRY133
The ICH2, ICH2-M, ICH3, ICH3-M, ICH3-S, ICH-4 and CICH chips can
support UDMA133 in hardware, even though the specifications of
the chips say otherwise. By enabling this option, you allow the
driver to enable the UDMA133 mode on these chips. Note that if
it doesn't work, your data gets lost, you're on your own, don't
expect any help.
Say N here, unless you really know what are you doing.
CONFIG_BLK_DEV_PDC202XX CONFIG_BLK_DEV_PDC202XX
Promise Ultra33 or PDC20246 Promise Ultra33 or PDC20246
Promise Ultra66 or PDC20262 Promise Ultra66 or PDC20262
......
...@@ -52,9 +52,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -52,9 +52,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_mbool ' HPT34X AUTODMA support (EXPERMENTAL)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_EXPERIMENTAL dep_mbool ' HPT34X AUTODMA support (EXPERMENTAL)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_EXPERIMENTAL
dep_bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Intel and Efar (SMsC) chipset support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Intel and Efar (SMsC) chipset support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI
if [ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
dep_bool ' Allow undocumented UDMA133 on ICH chips (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TRY133 $CONFIG_EXPERIMENTAL
fi
if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO
......
/* /*
* *
* $Id: aec62xx.c,v 1.0 2002/05/24 14:37:19 vojtech Exp $ * aec62xx.c, v1.2 2002/05/24
* *
* Copyright (c) 2002 Vojtech Pavlik * Copyright (c) 2002 Vojtech Pavlik
* *
...@@ -60,7 +60,9 @@ ...@@ -60,7 +60,9 @@
#define AEC_PLLCLK_ATA133 0x10 #define AEC_PLLCLK_ATA133 0x10
#define AEC_CABLEPINS_INPUT 0x10 #define AEC_CABLEPINS_INPUT 0x10
static unsigned char aec_cyc2udma[17] = { 0, 0, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1 }; static unsigned char aec_cyc2udma[9] = { 5, 5, 5, 4, 3, 2, 2, 1, 1 };
static unsigned char aec_cyc2act[16] = { 1, 1, 2, 3, 4, 5, 6, 0, 0, 7, 7, 7, 7, 7, 7, 7 };
static unsigned char aec_cyc2rec[16] = { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 12, 13, 14 };
/* /*
* aec_set_speed_old() writes timing values to * aec_set_speed_old() writes timing values to
...@@ -71,8 +73,10 @@ static void aec_set_speed_old(struct pci_dev *dev, unsigned char dn, struct ata_ ...@@ -71,8 +73,10 @@ static void aec_set_speed_old(struct pci_dev *dev, unsigned char dn, struct ata_
{ {
unsigned char t; unsigned char t;
pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1), FIT(timing->active, 0, 15)); pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1),
pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1, FIT(timing->recover, 0, 15)); aec_cyc2act[FIT(timing->active, 0, 15)]);
pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1,
aec_cyc2rec[FIT(timing->recover, 0, 15)]);
pci_read_config_byte(dev, AEC_UDMA_OLD, &t); pci_read_config_byte(dev, AEC_UDMA_OLD, &t);
t &= ~(3 << (dn << 1)); t &= ~(3 << (dn << 1));
...@@ -91,12 +95,19 @@ static void aec_set_speed_new(struct pci_dev *dev, unsigned char dn, struct ata_ ...@@ -91,12 +95,19 @@ static void aec_set_speed_new(struct pci_dev *dev, unsigned char dn, struct ata_
unsigned char t; unsigned char t;
pci_write_config_byte(dev, AEC_DRIVE_TIMING + dn, pci_write_config_byte(dev, AEC_DRIVE_TIMING + dn,
(FIT(timing->active, 0, 15) << 4) | FIT(timing->recover, 0, 15)); (aec_cyc2act[FIT(timing->active, 0, 15)] << 4)
| aec_cyc2rec[FIT(timing->recover, 0, 15)]);
pci_read_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), &t); pci_read_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), &t);
t &= ~(0xf << ((dn & 1) << 2)); t &= ~(0xf << ((dn & 1) << 2));
if (timing->udma) if (timing->udma) {
t |= aec_cyc2udma[FIT(timing->udma, 2, 16)] << ((dn & 1) << 2); if (timing->udma >= 2)
t |= aec_cyc2udma[FIT(timing->udma, 2, 8)] << ((dn & 1) << 2);
if (timing->mode == XFER_UDMA_5)
t |= 6;
if (timing->mode == XFER_UDMA_6)
t |= 7;
}
pci_write_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), t); pci_write_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), t);
} }
...@@ -120,9 +131,10 @@ static int aec_set_drive(struct ata_device *drive, unsigned char speed) ...@@ -120,9 +131,10 @@ static int aec_set_drive(struct ata_device *drive, unsigned char speed)
drive->dn >> 1, drive->dn & 1); drive->dn >> 1, drive->dn & 1);
T = 1000000000 / system_bus_speed; T = 1000000000 / system_bus_speed;
UT = T / (aec_old ? 1 : 4); UT = T / (aec_old ? 1 : 2);
ata_timing_compute(drive, speed, &t, T, UT); ata_timing_compute(drive, speed, &t, T, UT);
ata_timing_merge_8bit(&t);
if (aec_old) if (aec_old)
aec_set_speed_old(drive->channel->pci_dev, drive->dn, &t); aec_set_speed_old(drive->channel->pci_dev, drive->dn, &t);
......
...@@ -136,6 +136,20 @@ short ata_timing_mode(struct ata_device *drive, int map) ...@@ -136,6 +136,20 @@ short ata_timing_mode(struct ata_device *drive, int map)
(drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW; (drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW;
} }
/*
* Just get a pointer to the struct describing the timing values used commonly
* for a particular mode.
*/
struct ata_timing* ata_timing_data(short speed)
{
struct ata_timing *t;
for (t = ata_timing; t->mode != speed; t++)
if (t->mode < 0)
return NULL;
return t;
}
/* /*
* This is just unit conversion. * This is just unit conversion.
*/ */
...@@ -179,17 +193,15 @@ void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, ...@@ -179,17 +193,15 @@ void ata_timing_merge(struct ata_timing *a, struct ata_timing *b,
} }
/* /*
* Just get a pointer to the struct describing the timing values used commonly * Not all controllers can do separate timing for 8-bit command transfers
* for a particular mode. * and 16-bit data transfers.
*/ */
struct ata_timing* ata_timing_data(short speed)
{
struct ata_timing *t;
for (t = ata_timing; t->mode != speed; t++) void ata_timing_merge_8bit(struct ata_timing *t)
if (t->mode < 0) {
return NULL; t->active = max(t->active, t->act8b);
return t; t->recover = max(t->recover, t->rec8b);
t->cycle = max(t->cycle, t->cyc8b);
} }
int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t, int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t,
...@@ -204,6 +216,8 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing ...@@ -204,6 +216,8 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing
if (!(s = ata_timing_data(speed))) if (!(s = ata_timing_data(speed)))
return -EINVAL; return -EINVAL;
memcpy(t, s, sizeof(struct ata_timing));
/* If the drive is an EIDE drive, it can tell us it needs extended /* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing. * PIO/MWDMA cycle timing.
*/ */
...@@ -229,7 +243,7 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing ...@@ -229,7 +243,7 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing
/* Convert the timing to bus clock counts. /* Convert the timing to bus clock counts.
*/ */
ata_timing_quantize(s, t, T, UT); ata_timing_quantize(t, t, T, UT);
/* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, /* Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
* S.M.A.R.T and some other commands. We have to ensure that the DMA * S.M.A.R.T and some other commands. We have to ensure that the DMA
......
...@@ -69,7 +69,7 @@ extern struct ata_timing ata_timing[]; ...@@ -69,7 +69,7 @@ extern struct ata_timing ata_timing[];
#define XFER_EPIO 0x01 #define XFER_EPIO 0x01
#define XFER_PIO 0x00 #define XFER_PIO 0x00
/* External interface to host chips chanell timing setup. /* External interface to host chips channel timing setup.
* *
* It's a bit elaborate due to the legacy we have to bear. * It's a bit elaborate due to the legacy we have to bear.
*/ */
...@@ -79,6 +79,7 @@ extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q, ...@@ -79,6 +79,7 @@ extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q,
int T, int UT); int T, int UT);
extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b,
struct ata_timing *m, unsigned int what); struct ata_timing *m, unsigned int what);
void ata_timing_merge_8bit(struct ata_timing *t);
extern struct ata_timing* ata_timing_data(short speed); extern struct ata_timing* ata_timing_data(short speed);
extern int ata_timing_compute(struct ata_device *drive, extern int ata_timing_compute(struct ata_device *drive,
short speed, struct ata_timing *t, int T, int UT); short speed, struct ata_timing *t, int T, int UT);
......
...@@ -266,11 +266,10 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq) ...@@ -266,11 +266,10 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK) if (drive->type == ATA_DISK) {
return 0; ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ }
OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0; return 0;
} }
......
...@@ -281,7 +281,7 @@ static int ide_build_sglist(struct ata_device *drive, struct request *rq) ...@@ -281,7 +281,7 @@ static int ide_build_sglist(struct ata_device *drive, struct request *rq)
struct scatterlist *sg = ch->sg_table; struct scatterlist *sg = ch->sg_table;
int nents; int nents;
if (rq->flags & REQ_SPECIAL) { if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) {
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
...@@ -521,7 +521,7 @@ icside_dma_common(struct ata_device *drive, struct request *rq, ...@@ -521,7 +521,7 @@ icside_dma_common(struct ata_device *drive, struct request *rq,
static int icside_dma_init(struct ata_device *drive, struct request *rq) static int icside_dma_init(struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
unsigned int cmd; u8 int cmd;
if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
return 1; return 1;
...@@ -529,7 +529,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq) ...@@ -529,7 +529,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq)
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
ide_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL); ata_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL);
if ((rq->flags & REQ_SPECIAL) && drive->addressing == 1) { if ((rq->flags & REQ_SPECIAL) && drive->addressing == 1) {
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
...@@ -542,6 +542,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq) ...@@ -542,6 +542,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq)
OUT_BYTE(cmd, IDE_COMMAND_REG); OUT_BYTE(cmd, IDE_COMMAND_REG);
enable_dma(ch->hw.dma); enable_dma(ch->hw.dma);
return 0; return 0;
} }
......
...@@ -728,6 +728,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -728,6 +728,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
int xferlen, int xferlen,
ata_handler_t handler) ata_handler_t handler)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
ide_startstop_t startstop; ide_startstop_t startstop;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
...@@ -735,6 +737,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -735,6 +737,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
if (ide_wait_stat(&startstop, drive, rq, 0, BUSY_STAT, WAIT_READY)) if (ide_wait_stat(&startstop, drive, rq, 0, BUSY_STAT, WAIT_READY))
return startstop; return startstop;
spin_lock_irqsave(ch->lock, flags);
if (info->dma) { if (info->dma) {
if (info->cmd == READ || info->cmd == WRITE) if (info->cmd == READ || info->cmd == WRITE)
info->dma = !udma_init(drive, rq); info->dma = !udma_init(drive, rq);
...@@ -754,11 +758,18 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -754,11 +758,18 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
udma_start(drive, rq); udma_start(drive, rq);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
ide_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry); ata_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} else { } else {
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
spin_unlock_irqrestore(ch->lock, flags);
/* FIXME: Woah we have to ungrab the lock before the IRQ
* handler gets called.
*/
return handler(drive, rq); return handler(drive, rq);
} }
} }
...@@ -773,6 +784,8 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, ...@@ -773,6 +784,8 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive,
unsigned char *cmd, unsigned long timeout, unsigned char *cmd, unsigned long timeout,
ata_handler_t handler) ata_handler_t handler)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
ide_startstop_t startstop; ide_startstop_t startstop;
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
...@@ -789,11 +802,11 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, ...@@ -789,11 +802,11 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive,
return startstop; return startstop;
} }
/* Arm the interrupt handler. */ /* Arm the interrupt handler and send the command to the device. */
ide_set_handler(drive, handler, timeout, cdrom_timer_expiry); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, handler, timeout, cdrom_timer_expiry);
/* Send the command to the device. */
atapi_write(drive, cmd, CDROM_PACKET_SIZE); atapi_write(drive, cmd, CDROM_PACKET_SIZE);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -893,6 +906,8 @@ int cdrom_read_check_ireason(struct ata_device *drive, struct request *rq, int l ...@@ -893,6 +906,8 @@ int cdrom_read_check_ireason(struct ata_device *drive, struct request *rq, int l
*/ */
static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
int stat; int stat;
int ireason, len, sectors_to_transfer, nskip; int ireason, len, sectors_to_transfer, nskip;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
...@@ -1007,7 +1022,9 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request ...@@ -1007,7 +1022,9 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
} }
/* Done moving data! Wait for another interrupt. */ /* Done moving data! Wait for another interrupt. */
ide_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -1234,6 +1251,8 @@ static ide_startstop_t cdrom_start_read(struct ata_device *drive, struct request ...@@ -1234,6 +1251,8 @@ static ide_startstop_t cdrom_start_read(struct ata_device *drive, struct request
/* Interrupt routine for packet command completion. */ /* Interrupt routine for packet command completion. */
static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
int ireason, len, stat, thislen; int ireason, len, stat, thislen;
/* FIXME --mdcki */ /* FIXME --mdcki */
...@@ -1326,7 +1345,9 @@ static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *r ...@@ -1326,7 +1345,9 @@ static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *r
} }
/* Now we wait for another interrupt. */ /* Now we wait for another interrupt. */
ide_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -1469,6 +1490,8 @@ static inline int cdrom_write_check_ireason(struct ata_device *drive, struct req ...@@ -1469,6 +1490,8 @@ static inline int cdrom_write_check_ireason(struct ata_device *drive, struct req
static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
int stat, ireason, len, sectors_to_transfer, uptodate; int stat, ireason, len, sectors_to_transfer, uptodate;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
int dma_error = 0, dma = info->dma; int dma_error = 0, dma = info->dma;
...@@ -1559,7 +1582,9 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request ...@@ -1559,7 +1582,9 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
} }
/* re-arm handler */ /* re-arm handler */
ide_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
......
...@@ -95,8 +95,9 @@ static int lba_capacity_is_ok(struct hd_driveid *id) ...@@ -95,8 +95,9 @@ static int lba_capacity_is_ok(struct hd_driveid *id)
*/ */
static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq)
{ {
char *buf = NULL;
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel;
char *buf = NULL;
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) if (drive->status & (ERR_STAT|DRQ_STAT))
...@@ -106,7 +107,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq ...@@ -106,7 +107,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
#if 0 #if 0
printk("task_in_intr to Soon wait for next interrupt\n"); printk("task_in_intr to Soon wait for next interrupt\n");
#endif #endif
ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -132,8 +140,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq ...@@ -132,8 +140,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
return ide_stopped; return ide_stopped;
} }
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
/* still data left to transfer */ /* still data left to transfer */
ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -143,8 +157,9 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq ...@@ -143,8 +157,9 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
*/ */
static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq)
{ {
char *buf = NULL;
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel;
char *buf = NULL;
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__);
...@@ -165,7 +180,13 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r ...@@ -165,7 +180,13 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r
rq->current_nr_sectors--; rq->current_nr_sectors--;
} }
ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_out_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -175,16 +196,25 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r ...@@ -175,16 +196,25 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r
*/ */
static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq)
{ {
char *buf = NULL;
unsigned int msect, nsect;
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel;
char *buf = NULL;
unsigned int msect;
unsigned int nsect;
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) if (drive->status & (ERR_STAT|DRQ_STAT))
return ata_error(drive, rq, __FUNCTION__); return ata_error(drive, rq, __FUNCTION__);
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
/* no data yet, so wait for another interrupt */ /* no data yet, so wait for another interrupt */
ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -213,17 +243,24 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request ...@@ -213,17 +243,24 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
} }
} while (msect); } while (msect);
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
/* /*
* more data left * more data left
*/ */
ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
int ok; int ok;
int mcount = drive->mult_count; int mcount = drive->mult_count;
ide_startstop_t startstop; ide_startstop_t startstop;
...@@ -255,8 +292,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -255,8 +292,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
if (!ok) { if (!ok) {
/* no data yet, so wait for another interrupt */ /* no data yet, so wait for another interrupt */
if (!drive->channel->handler) if (!ch->handler) {
ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
}
return ide_started; return ide_started;
} }
...@@ -298,8 +342,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -298,8 +342,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
} while (mcount); } while (mcount);
rq->errors = 0; rq->errors = 0;
if (!drive->channel->handler) if (!ch->handler) {
ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
}
return ide_started; return ide_started;
} }
......
...@@ -821,6 +821,8 @@ static void idefloppy_retry_pc(struct ata_device *drive) ...@@ -821,6 +821,8 @@ static void idefloppy_retry_pc(struct ata_device *drive)
*/ */
static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_status_reg_t status; idefloppy_status_reg_t status;
idefloppy_bcount_reg_t bcount; idefloppy_bcount_reg_t bcount;
...@@ -833,7 +835,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -833,7 +835,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
#endif #endif
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
if (udma_stop(drive)) { if (udma_stop(drive)) {
set_bit (PC_DMA_ERROR, &pc->flags); set_bit (PC_DMA_ERROR, &pc->flags);
} else { } else {
...@@ -883,15 +885,24 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -883,15 +885,24 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
return ide_stopped; return ide_stopped;
} }
#endif #endif
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */
ireason.all=IN_BYTE (IDE_IREASON_REG); ireason.all=IN_BYTE (IDE_IREASON_REG);
if (ireason.b.cod) { if (ireason.b.cod) {
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
return ide_stopped; return ide_stopped;
} }
if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read");
printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write");
return ide_stopped; return ide_stopped;
...@@ -901,8 +912,11 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -901,8 +912,11 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
if ( temp > pc->request_transfer) { if ( temp > pc->request_transfer) {
if (temp > pc->buffer_size) { if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n");
atapi_discard_data (drive,bcount.all); atapi_discard_data (drive,bcount.all);
ide_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); ata_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
#if IDEFLOPPY_DEBUG_LOG #if IDEFLOPPY_DEBUG_LOG
...@@ -924,7 +938,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -924,7 +938,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
pc->actually_transferred+=bcount.all; /* Update the current position */ pc->actually_transferred+=bcount.all; /* Update the current position */
pc->current_position+=bcount.all; pc->current_position+=bcount.all;
ide_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ ata_set_handler(drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -936,6 +951,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -936,6 +951,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
*/ */
static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct request *rq) static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
ide_startstop_t startstop; ide_startstop_t startstop;
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_ireason_reg_t ireason; idefloppy_ireason_reg_t ireason;
...@@ -944,14 +961,23 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re ...@@ -944,14 +961,23 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re
printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ireason.all=IN_BYTE (IDE_IREASON_REG); ireason.all=IN_BYTE (IDE_IREASON_REG);
if (!ireason.b.cod || ireason.b.io) { if (!ireason.b.cod || ireason.b.io) {
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped; return ide_stopped;
} }
ide_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ ata_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */ atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -979,6 +1005,8 @@ static int idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq ...@@ -979,6 +1005,8 @@ static int idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq
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)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
ide_startstop_t startstop; ide_startstop_t startstop;
idefloppy_ireason_reg_t ireason; idefloppy_ireason_reg_t ireason;
...@@ -987,22 +1015,32 @@ static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct r ...@@ -987,22 +1015,32 @@ static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct r
printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ireason.all=IN_BYTE (IDE_IREASON_REG); ireason.all=IN_BYTE (IDE_IREASON_REG);
if (!ireason.b.cod || ireason.b.io) { if (!ireason.b.cod || ireason.b.io) {
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped; return ide_stopped;
} }
/* /*
* The following delay solves a problem with ATAPI Zip 100 drives where the * The following delay solves a problem with ATAPI Zip 100 drives where
* Busy flag was apparently being deasserted before the unit was ready to * the Busy flag was apparently being deasserted before the unit was
* receive data. This was happening on a 1200 MHz Athlon system. 10/26/01 * ready to receive data. This was happening on a 1200 MHz Athlon
* 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will * system. 10/26/01 25msec is too short, 40 and 50msec work well.
* not be actually used until after the packet is moved in about 50 msec. * idefloppy_pc_intr will not be actually used until after the packet
* is moved in about 50 msec.
*/ */
ide_set_handler(drive, ata_set_handler(drive,
idefloppy_pc_intr, /* service routine for packet command */ idefloppy_pc_intr, /* service routine for packet command */
floppy->ticks, /* wait this long before "failing" */ floppy->ticks, /* wait this long before "failing" */
idefloppy_transfer_pc2); /* fail == transfer_pc2 */ idefloppy_transfer_pc2); /* fail == transfer_pc2 */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -1047,7 +1085,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque ...@@ -1047,7 +1085,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
} }
#if IDEFLOPPY_DEBUG_LOG #if IDEFLOPPY_DEBUG_LOG
printk (KERN_INFO "Retry number - %d\n",pc->retries); printk (KERN_INFO "Retry number - %d\n",pc->retries);
#endif /* IDEFLOPPY_DEBUG_LOG */ #endif
pc->retries++; pc->retries++;
pc->actually_transferred=0; /* We haven't transferred any data yet */ pc->actually_transferred=0; /* We haven't transferred any data yet */
...@@ -1082,9 +1120,19 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque ...@@ -1082,9 +1120,19 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */ pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */
} }
if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
ide_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} else { } else {
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
...@@ -1750,8 +1798,6 @@ static void idefloppy_release(struct inode *inode, struct file *filp, struct ata ...@@ -1750,8 +1798,6 @@ static void idefloppy_release(struct inode *inode, struct file *filp, struct ata
if (!drive->usage) { if (!drive->usage) {
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
invalidate_bdev (inode->i_bdev, 0);
/* IOMEGA Clik! drives do not support lock/unlock commands */ /* IOMEGA Clik! drives do not support lock/unlock commands */
if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 0); idefloppy_create_prevent_cmd (&pc, 0);
......
/* /*
* linux/drivers/ide/ide-pmac.c Version ?.?? Mar. 18, 2000
*
* Support for IDE interfaces on PowerMacs. * Support for IDE interfaces on PowerMacs.
* These IDE interfaces are memory-mapped and have a DBDMA channel * These IDE interfaces are memory-mapped and have a DBDMA channel
* for doing DMA. * for doing DMA.
...@@ -1436,7 +1434,8 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq) ...@@ -1436,7 +1434,8 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL);
ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL);
if ((rq->flags & REQ_SPECIAL) && if ((rq->flags & REQ_SPECIAL) &&
(drive->addressing == 1)) { (drive->addressing == 1)) {
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
......
...@@ -892,7 +892,7 @@ typedef struct { ...@@ -892,7 +892,7 @@ typedef struct {
struct bio *bio; struct bio *bio;
char *b_data; char *b_data;
int b_count; int b_count;
/* /*
* Pipeline parameters. * Pipeline parameters.
* *
...@@ -1864,6 +1864,7 @@ static int idetape_end_request(struct ata_device *drive, struct request *rq, int ...@@ -1864,6 +1864,7 @@ static int idetape_end_request(struct ata_device *drive, struct request *rq, int
idetape_increase_max_pipeline_stages (drive); idetape_increase_max_pipeline_stages (drive);
} }
} }
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
drive->rq = NULL; drive->rq = NULL;
end_that_request_last(rq); end_that_request_last(rq);
...@@ -1977,6 +1978,8 @@ static void idetape_postpone_request(struct ata_device *drive, struct request *r ...@@ -1977,6 +1978,8 @@ static void idetape_postpone_request(struct ata_device *drive, struct request *r
*/ */
static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
idetape_tape_t *tape = drive->driver_data; idetape_tape_t *tape = drive->driver_data;
idetape_status_reg_t status; idetape_status_reg_t status;
idetape_bcount_reg_t bcount; idetape_bcount_reg_t bcount;
...@@ -2080,15 +2083,24 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request ...@@ -2080,15 +2083,24 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request
return ide_stopped; return ide_stopped;
} }
#endif #endif
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */
ireason.all = IN_BYTE (IDE_IREASON_REG); ireason.all = IN_BYTE (IDE_IREASON_REG);
if (ireason.b.cod) { if (ireason.b.cod) {
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
return ide_stopped; return ide_stopped;
} }
if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read");
printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
return ide_stopped; return ide_stopped;
...@@ -2099,7 +2111,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request ...@@ -2099,7 +2111,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request
if (temp > pc->buffer_size) { if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
atapi_discard_data (drive, bcount.all); atapi_discard_data (drive, bcount.all);
ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
#if IDETAPE_DEBUG_LOG #if IDETAPE_DEBUG_LOG
...@@ -2125,7 +2139,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request ...@@ -2125,7 +2139,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request
if (tape->debug_level >= 2) if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
#endif #endif
ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -2173,6 +2189,8 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request ...@@ -2173,6 +2189,8 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request
*/ */
static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct request *rq) static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
idetape_tape_t *tape = drive->driver_data; idetape_tape_t *tape = drive->driver_data;
struct atapi_packet_command *pc = tape->pc; struct atapi_packet_command *pc = tape->pc;
idetape_ireason_reg_t ireason; idetape_ireason_reg_t ireason;
...@@ -2183,6 +2201,12 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ ...@@ -2183,6 +2201,12 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ
printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ireason.all = IN_BYTE (IDE_IREASON_REG); ireason.all = IN_BYTE (IDE_IREASON_REG);
while (retries-- && (!ireason.b.cod || ireason.b.io)) { while (retries-- && (!ireason.b.cod || ireason.b.io)) {
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n");
...@@ -2196,11 +2220,14 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ ...@@ -2196,11 +2220,14 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ
} }
if (!ireason.b.cod || ireason.b.io) { if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
tape->cmd_start_time = jiffies; tape->cmd_start_time = jiffies;
ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive,pc->c,12); /* Send the actual packet */ atapi_write(drive,pc->c,12); /* Send the actual packet */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -2274,8 +2301,18 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, ...@@ -2274,8 +2301,18 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive,
} }
#endif #endif
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
ide_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} else { } else {
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
...@@ -3326,7 +3363,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive) ...@@ -3326,7 +3363,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive)
tape->merge_stage = NULL; tape->merge_stage = NULL;
} }
tape->chrdev_direction = idetape_direction_none; tape->chrdev_direction = idetape_direction_none;
if (tape->first_stage == NULL) if (tape->first_stage == NULL)
return 0; return 0;
...@@ -3723,10 +3760,10 @@ static int idetape_add_chrdev_write_request(struct ata_device *drive, int blocks ...@@ -3723,10 +3760,10 @@ static int idetape_add_chrdev_write_request(struct ata_device *drive, int blocks
#if IDETAPE_DEBUG_LOG #if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3) if (tape->debug_level >= 3)
printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n"); printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n");
#endif /* IDETAPE_DEBUG_LOG */ #endif
/* /*
* Attempt to allocate a new stage. * Attempt to allocate a new stage.
* Pay special attention to possible race conditions. * Pay special attention to possible race conditions.
*/ */
while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
......
...@@ -199,13 +199,21 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -199,13 +199,21 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
IDE_SELECT_REG); IDE_SELECT_REG);
if (ar->handler) { if (ar->handler) {
unsigned long flags;
struct ata_channel *ch = drive->channel;
/* This is apparently supposed to reset the wait timeout for /* This is apparently supposed to reset the wait timeout for
* the interrupt to accur. * the interrupt to accur.
*/ */
ide_set_handler(drive, ar->handler, WAIT_CMD, NULL); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, ar->handler, WAIT_CMD, NULL);
OUT_BYTE(ar->cmd, IDE_COMMAND_REG); OUT_BYTE(ar->cmd, IDE_COMMAND_REG);
spin_unlock_irqrestore(ch->lock, flags);
/* FIXME: Warning check for race between handler and prehandler /* FIXME: Warning check for race between handler and prehandler
* for writing first block of data. however since we are well * for writing first block of data. however since we are well
...@@ -373,8 +381,12 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct ...@@ -373,8 +381,12 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct
struct ata_taskfile *ar = rq->special; struct ata_taskfile *ar = rq->special;
ide_startstop_t ret = ide_stopped; ide_startstop_t ret = ide_stopped;
unsigned long flags;
ide__sti(); /* local CPU only */ ide__sti(); /* local CPU only */
spin_lock_irqsave(drive->channel->lock, flags);
if (rq->buffer && ar->taskfile.sector_number) { if (rq->buffer && ar->taskfile.sector_number) {
if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) { if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) {
int retries = 10; int retries = 10;
...@@ -409,6 +421,8 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct ...@@ -409,6 +421,8 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct
drive->rq = NULL; drive->rq = NULL;
end_that_request_last(rq); end_that_request_last(rq);
spin_unlock_irqrestore(drive->channel->lock, flags);
return ret; return ret;
} }
......
...@@ -160,25 +160,25 @@ int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate) ...@@ -160,25 +160,25 @@ int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate)
* at the appropriate code to handle the next interrupt, and a * at the appropriate code to handle the next interrupt, and a
* timer is started to prevent us from waiting forever in case * timer is started to prevent us from waiting forever in case
* something goes wrong (see the ide_timer_expiry() handler later on). * something goes wrong (see the ide_timer_expiry() handler later on).
*
* Channel lock should be held.
*/ */
void ide_set_handler(struct ata_device *drive, ata_handler_t handler, 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)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
spin_lock_irqsave(ch->lock, flags); if (ch->handler)
printk("%s: %s: handler not null; old=%p, new=%p, from %p\n",
drive->name, __FUNCTION__, ch->handler, handler, __builtin_return_address(0));
if (ch->handler != NULL) {
printk("%s: ide_set_handler: handler not null; old=%p, new=%p, from %p\n",
drive->name, ch->handler, handler, __builtin_return_address(0));
}
ch->handler = handler; ch->handler = handler;
ch->expiry = expiry; ch->expiry = expiry;
ch->timer.expires = jiffies + timeout; ch->timer.expires = jiffies + timeout;
add_timer(&ch->timer); add_timer(&ch->timer);
spin_unlock_irqrestore(ch->lock, flags);
} }
static void check_crc_errors(struct ata_device *drive) static void check_crc_errors(struct ata_device *drive)
...@@ -256,26 +256,30 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */ ...@@ -256,26 +256,30 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
*/ */
static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq) static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
int ret = ide_stopped;
ata_select(drive, 10); ata_select(drive, 10);
if (ata_status(drive, 0, BUSY_STAT)) if (!ata_status(drive, 0, BUSY_STAT)) {
printk("%s: ATAPI reset complete\n", drive->name);
else {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler (drive, atapi_reset_pollfunc, HZ/20, NULL); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
spin_unlock_irqrestore(ch->lock, flags);
ret = ide_started; /* continue polling */
} else {
ch->poll_timeout = 0; /* end of polling */
printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status);
return ide_started; /* continue polling */ ret = do_reset1(drive, 1); /* do it the old fashioned way */
} }
ch->poll_timeout = 0; /* end of polling */ } else {
printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status); printk("%s: ATAPI reset complete\n", drive->name);
ch->poll_timeout = 0; /* done polling */
return do_reset1(drive, 1); /* do it the old fashioned way */
} }
ch->poll_timeout = 0; /* done polling */
return ide_stopped; return ret;
} }
/* /*
...@@ -289,12 +293,16 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -289,12 +293,16 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
if (!ata_status(drive, 0, BUSY_STAT)) { if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); unsigned long flags;
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; /* continue polling */ return ide_started; /* continue polling */
} }
printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status); printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
drive->failures++; ++drive->failures;
} else { } else {
u8 stat; u8 stat;
...@@ -303,11 +311,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -303,11 +311,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
printk("success\n"); printk("success\n");
drive->failures = 0; drive->failures = 0;
} else { } else {
char *msg; const char *msg = "";
#if FANCY_STATUS_DUMPS #if FANCY_STATUS_DUMPS
u8 val; u8 val;
static char *messages[5] = { static const char *messages[5] = {
" passed", " passed",
" formatter device", " formatter device",
" sector buffer", " sector buffer",
...@@ -319,13 +327,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -319,13 +327,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
val = stat & 0x7f; val = stat & 0x7f;
if (val >= 1 && val <= 5) if (val >= 1 && val <= 5)
msg = messages[val -1]; msg = messages[val -1];
else
msg = "";
if (stat & 0x80) if (stat & 0x80)
printk("; slave:"); printk("; slave:");
#endif #endif
printk("%s error [%02x]\n", msg, stat); printk(KERN_ERR "%s error [%02x]\n", msg, stat);
drive->failures++; ++drive->failures;
} }
} }
ch->poll_timeout = 0; /* done polling */ ch->poll_timeout = 0; /* done polling */
...@@ -347,6 +353,8 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -347,6 +353,8 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
* Equally poor, though, is the fact that this may a very long time to * 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 * complete, (up to 30 seconds worst case). So, instead of busy-waiting here
* for it, we set a timer to poll at 50ms intervals. * for it, we set a timer to poll at 50ms intervals.
*
* Channel lock should be held.
*/ */
static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
...@@ -364,7 +372,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -364,7 +372,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
ata_select(drive, 20); ata_select(drive, 20);
OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
ch->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
return ide_started; return ide_started;
...@@ -377,7 +385,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -377,7 +385,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit)
check_crc_errors(&ch->drives[unit]); check_crc_errors(&ch->drives[unit]);
__restore_flags (flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
return ide_started; return ide_started;
} }
...@@ -546,6 +554,8 @@ static int do_recalibrate(struct ata_device *drive) ...@@ -546,6 +554,8 @@ static int do_recalibrate(struct ata_device *drive)
/* /*
* Take action based on the error returned by the drive. * Take action based on the error returned by the drive.
*
* FIXME: Channel lock should be held.
*/ */
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)
{ {
...@@ -613,6 +623,8 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -613,6 +623,8 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
* That could be done by busy-waiting for the first jiffy or two, and then * That could be done by busy-waiting for the first jiffy or two, and then
* setting a timer to wake up at half second intervals thereafter, until * setting a timer to wake up at half second intervals thereafter, until
* timeout is achieved, before timing out. * timeout is achieved, before timing out.
*
* FIXME: Channel lock should be held.
*/ */
int ide_wait_stat(ide_startstop_t *startstop, int ide_wait_stat(ide_startstop_t *startstop,
struct ata_device *drive, struct request *rq, struct ata_device *drive, struct request *rq,
...@@ -709,7 +721,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -709,7 +721,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
/* This issues a special drive command. /* This issues a special drive command.
*/ */
if (rq->flags & REQ_SPECIAL) if (rq->flags & REQ_SPECIAL)
return ata_taskfile(drive, rq->special, NULL); if (drive->type == ATA_DISK)
return ata_taskfile(drive, rq->special, NULL);
/* The normal way of execution is to pass and execute the request /* The normal way of execution is to pass and execute the request
* handler down to the device type driver. * handler down to the device type driver.
...@@ -744,6 +757,7 @@ ide_startstop_t restart_request(struct ata_device *drive) ...@@ -744,6 +757,7 @@ ide_startstop_t restart_request(struct ata_device *drive)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
unsigned long flags; unsigned long flags;
int ret;
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
...@@ -752,7 +766,12 @@ ide_startstop_t restart_request(struct ata_device *drive) ...@@ -752,7 +766,12 @@ ide_startstop_t restart_request(struct ata_device *drive)
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return start_request(drive, drive->rq); /* FIXME make start_request do the unlock itself and
* push this locking further down. */
ret = start_request(drive, drive->rq);
return ret;
} }
/* /*
...@@ -844,14 +863,16 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel) ...@@ -844,14 +863,16 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel)
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 "ide_set_handler: timer already active\n"); 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 */ /* we purposely leave hwgroup busy while sleeping */
} else { } 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? */ /* Ugly, but how can we sleep for the lock otherwise? */
ide_release_lock(&irq_lock);/* for atari only */ ide_release_lock(&ide_irq_lock);/* for atari only */
clear_bit(IDE_BUSY, channel->active); clear_bit(IDE_BUSY, channel->active);
} }
...@@ -918,11 +939,10 @@ static void queue_commands(struct ata_device *drive) ...@@ -918,11 +939,10 @@ static void queue_commands(struct ata_device *drive)
drive->rq = rq; drive->rq = rq;
/* FIXME: push this locaing further down */
spin_unlock(drive->channel->lock); spin_unlock(drive->channel->lock);
ide__sti(); /* allow other IRQs while we start this request */ ide__sti(); /* allow other IRQs while we start this request */
startstop = start_request(drive, rq); startstop = start_request(drive, rq);
spin_lock_irq(drive->channel->lock); spin_lock_irq(drive->channel->lock);
/* command started, we are busy */ /* command started, we are busy */
...@@ -948,7 +968,7 @@ static void queue_commands(struct ata_device *drive) ...@@ -948,7 +968,7 @@ static void queue_commands(struct ata_device *drive)
*/ */
static void do_request(struct ata_channel *channel) static void do_request(struct ata_channel *channel)
{ {
ide_get_lock(&irq_lock, ata_irq_request, hwgroup);/* for atari only: POSSIBLY BROKEN HERE(?) */ 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 */ // __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
while (!test_and_set_bit(IDE_BUSY, channel->active)) { while (!test_and_set_bit(IDE_BUSY, channel->active)) {
...@@ -1142,7 +1162,7 @@ void ide_timer_expiry(unsigned long data) ...@@ -1142,7 +1162,7 @@ void ide_timer_expiry(unsigned long data)
* *
* In reality, this is a non-issue. The new command is not sent unless the * In reality, this is a non-issue. The new command is not sent unless the
* drive is ready to accept one, in which case we know the drive is not * drive is ready to accept one, in which case we know the drive is not
* trying to interrupt us. And ide_set_handler() is always invoked before * trying to interrupt us. And ata_set_handler() is always invoked before
* completing the issuance of any new drive command, so we will not be * completing the issuance of any new drive command, so we will not be
* accidentally invoked as a result of any valid command completion interrupt. * accidentally invoked as a result of any valid command completion interrupt.
* *
...@@ -1416,7 +1436,7 @@ EXPORT_SYMBOL(drive_is_flashcard); ...@@ -1416,7 +1436,7 @@ EXPORT_SYMBOL(drive_is_flashcard);
EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(do_ide_request); EXPORT_SYMBOL(do_ide_request);
EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ata_set_handler);
EXPORT_SYMBOL(ata_dump); EXPORT_SYMBOL(ata_dump);
EXPORT_SYMBOL(ata_error); EXPORT_SYMBOL(ata_error);
......
...@@ -47,15 +47,15 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) ...@@ -47,15 +47,15 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
u8 *argbuf = vals; u8 *argbuf = vals;
int argsize = 4; int argsize = 4;
struct ata_taskfile args; struct ata_taskfile args;
struct request rq; struct request req;
/* Second phase. /* Second phase.
*/ */
if (copy_from_user(vals, (void *)arg, 4)) if (copy_from_user(vals, (void *)arg, 4))
return -EFAULT; return -EFAULT;
memset(&rq, 0, sizeof(rq)); memset(&req, 0, sizeof(req));
rq.flags = REQ_SPECIAL; req.flags = REQ_SPECIAL;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -85,9 +85,9 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) ...@@ -85,9 +85,9 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
*/ */
args.handler = ata_special_intr; args.handler = ata_special_intr;
rq.buffer = argbuf + 4; req.buffer = argbuf + 4;
rq.special = &args; req.special = &args;
err = ide_do_drive_cmd(drive, &rq, ide_wait); err = ide_do_drive_cmd(drive, &req, ide_wait);
argbuf[0] = drive->status; argbuf[0] = drive->status;
argbuf[1] = args.taskfile.feature; argbuf[1] = args.taskfile.feature;
......
...@@ -114,12 +114,12 @@ spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; ...@@ -114,12 +114,12 @@ spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif #endif
#if defined(__mc68000__) || defined(CONFIG_APUS) #ifdef ATA_ARCH_LOCK
/* /*
* This is used by the Atari code to obtain access to the IDE interrupt, * This is used by the Atari code to obtain access to the IDE interrupt,
* which is shared between several drivers. * which is shared between several drivers.
*/ */
static int irq_lock; int ide_irq_lock;
#endif #endif
int noautodma = 0; int noautodma = 0;
...@@ -679,8 +679,8 @@ static int __init stridx (const char *s, char c) ...@@ -679,8 +679,8 @@ static int __init stridx (const char *s, char c)
*/ */
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"; static const char decimal[] = "0123456789";
static const char *hex = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
int i, n; int i, n;
if (*s++ == '=') { if (*s++ == '=') {
...@@ -1449,7 +1449,7 @@ static int __init ata_module_init(void) ...@@ -1449,7 +1449,7 @@ static int __init ata_module_init(void)
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
# if defined(__mc68000__) || defined(CONFIG_APUS) # if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
// ide_get_lock(&irq_lock, NULL, NULL);/* for atari only */ ide_get_lock(&ide_irq_lock, NULL, NULL);/* for atari only */
disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
// disable_irq_nosync(ide_hwifs[0].irq); // disable_irq_nosync(ide_hwifs[0].irq);
} }
...@@ -1460,7 +1460,7 @@ static int __init ata_module_init(void) ...@@ -1460,7 +1460,7 @@ static int __init ata_module_init(void)
# if defined(__mc68000__) || defined(CONFIG_APUS) # if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
enable_irq(ide_hwifs[0].irq); enable_irq(ide_hwifs[0].irq);
ide_release_lock(&irq_lock);/* for atari only */ ide_release_lock(&ide_irq_lock);/* for atari only */
} }
# endif # endif
#endif #endif
......
...@@ -64,7 +64,7 @@ static int build_sglist(struct ata_device *drive, struct request *rq) ...@@ -64,7 +64,7 @@ static int build_sglist(struct ata_device *drive, struct request *rq)
struct scatterlist *sg = ch->sg_table; struct scatterlist *sg = ch->sg_table;
int nents = 0; int nents = 0;
if (rq->flags & REQ_SPECIAL) { if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) {
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
#if 1 #if 1
unsigned char *virt_addr = rq->buffer; unsigned char *virt_addr = rq->buffer;
...@@ -388,7 +388,11 @@ int udma_new_table(struct ata_device *drive, struct request *rq) ...@@ -388,7 +388,11 @@ int udma_new_table(struct ata_device *drive, struct request *rq)
return count; return count;
} }
/* Teardown mappings after DMA has completed. */ /*
* Teardown mappings after DMA has completed.
*
* Channel lock should be held.
*/
void udma_destroy_table(struct ata_channel *ch) void udma_destroy_table(struct ata_channel *ch)
{ {
pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction); pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction);
...@@ -398,8 +402,9 @@ void udma_destroy_table(struct ata_channel *ch) ...@@ -398,8 +402,9 @@ void udma_destroy_table(struct ata_channel *ch)
* Prepare the channel for a DMA startfer. Please note that only the broken * Prepare the channel for a DMA startfer. Please note that only the broken
* Pacific Digital host chip needs the reques to be passed there to decide * Pacific Digital host chip needs the reques to be passed there to decide
* about addressing modes. * about addressing modes.
*
* Channel lock should be held.
*/ */
int udma_pci_start(struct ata_device *drive, struct request *rq) int udma_pci_start(struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
...@@ -414,6 +419,9 @@ int udma_pci_start(struct ata_device *drive, struct request *rq) ...@@ -414,6 +419,9 @@ int udma_pci_start(struct ata_device *drive, struct request *rq)
return 0; return 0;
} }
/*
* Channel lock should be held.
*/
int udma_pci_stop(struct ata_device *drive) int udma_pci_stop(struct ata_device *drive)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
...@@ -431,6 +439,8 @@ int udma_pci_stop(struct ata_device *drive) ...@@ -431,6 +439,8 @@ int udma_pci_stop(struct ata_device *drive)
/* /*
* FIXME: This should be attached to a channel as we can see now! * FIXME: This should be attached to a channel as we can see now!
*
* Channel lock should be held.
*/ */
int udma_pci_irq_status(struct ata_device *drive) int udma_pci_irq_status(struct ata_device *drive)
{ {
...@@ -517,6 +527,8 @@ void ata_init_dma(struct ata_channel *ch, unsigned long dma_base) ...@@ -517,6 +527,8 @@ void ata_init_dma(struct ata_channel *ch, unsigned long dma_base)
* *
* It's exported only for host chips which use it for fallback or (too) late * It's exported only for host chips which use it for fallback or (too) late
* capability checking. * capability checking.
*
* Channel lock should be held.
*/ */
int udma_pci_init(struct ata_device *drive, struct request *rq) int udma_pci_init(struct ata_device *drive, struct request *rq)
{ {
...@@ -534,7 +546,7 @@ int udma_pci_init(struct ata_device *drive, struct request *rq) ...@@ -534,7 +546,7 @@ int udma_pci_init(struct ata_device *drive, struct request *rq)
else else
cmd = 0x00; cmd = 0x00;
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); ata_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry);
if (drive->addressing) if (drive->addressing)
outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
else else
......
...@@ -428,7 +428,16 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -428,7 +428,16 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
if (drive->status & DRQ_STAT) if (drive->status & DRQ_STAT)
goto read_again; goto read_again;
if (drive->status & BUSY_STAT) { if (drive->status & BUSY_STAT) {
ide_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
#ifdef DEBUG_READ #ifdef DEBUG_READ
printk(KERN_DEBUG "%s: promise_read: waiting for" printk(KERN_DEBUG "%s: promise_read: waiting for"
"interrupt\n", drive->name); "interrupt\n", drive->name);
...@@ -456,7 +465,17 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc ...@@ -456,7 +465,17 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc
if (!ata_status(drive, 0, BUSY_STAT)) { if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above
* register file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; /* continue polling... */ return ide_started; /* continue polling... */
} }
ch->poll_timeout = 0; ch->poll_timeout = 0;
...@@ -531,16 +550,22 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int ...@@ -531,16 +550,22 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int
*/ */
static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq) static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
spin_lock_irqsave(ch->lock, flags);
if (inb(IDE_NSECTOR_REG) != 0) { if (inb(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; /* continue polling... */ return ide_started; /* continue polling... */
} }
ch->poll_timeout = 0; ch->poll_timeout = 0;
printk(KERN_ERR "%s: write timed out!\n", drive->name); printk(KERN_ERR "%s: write timed out!\n", drive->name);
ata_status(drive, 0, 0); ata_status(drive, 0, 0);
spin_unlock_irqrestore(ch->lock, flags);
return ata_error(drive, rq, "write timeout"); return ata_error(drive, rq, "write timeout");
} }
...@@ -549,11 +574,12 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r ...@@ -549,11 +574,12 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r
*/ */
promise_multwrite(drive, rq, 4); promise_multwrite(drive, rq, 4);
ch->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
drive->name, drive->status); drive->name, drive->status);
#endif #endif
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -566,6 +592,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r ...@@ -566,6 +592,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r
*/ */
static ide_startstop_t promise_do_write(struct ata_device *drive, struct request *rq) static ide_startstop_t promise_do_write(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
...@@ -573,26 +600,38 @@ static ide_startstop_t promise_do_write(struct ata_device *drive, struct request ...@@ -573,26 +600,38 @@ static ide_startstop_t promise_do_write(struct ata_device *drive, struct request
"buffer=%p\n", drive->name, rq->sector, "buffer=%p\n", drive->name, rq->sector,
rq->sector + rq->nr_sectors - 1, rq->buffer); rq->sector + rq->nr_sectors - 1, rq->buffer);
#endif #endif
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
/* /*
* If there are more than 4 sectors to transfer, do n-4 then go into * If there are more than 4 sectors to transfer, do n-4 then go into
* the polling strategy as defined above. * the polling strategy as defined above.
*/ */
if (rq->nr_sectors > 4) { if (rq->nr_sectors > 4) {
if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) {
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
}
ch->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} else { } else {
/* /*
* There are 4 or fewer sectors to transfer, do them all in one go * There are 4 or fewer sectors to transfer, do them all in one go
* and wait for NOT BUSY. * and wait for NOT BUSY.
*/ */
if (promise_multwrite(drive, rq, rq->nr_sectors)) if (promise_multwrite(drive, rq, rq->nr_sectors)) {
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
}
ch->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
spin_unlock_irqrestore(ch->lock, flags);
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
"status = %02x\n", drive->name, drive->status); "status = %02x\n", drive->name, drive->status);
...@@ -629,16 +668,19 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -629,16 +668,19 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
switch (rq_data_dir(rq)) { switch (rq_data_dir(rq)) {
case READ: case READ:
/*
* The card's behaviour is odd at this point. If the data is /*
* available, DRQ will be true, and no interrupt will be * The card's behaviour is odd at this point. If the data is
* generated by the card. If this is the case, we need to call the * available, DRQ will be true, and no interrupt will be
* "interrupt" handler (promise_read_intr) directly. Otherwise, if * generated by the card. If this is the case, we need to call
* an interrupt is going to occur, bit0 of the SELECT register will * the "interrupt" handler (promise_read_intr) directly.
* be high, so we can set the handler the just return and be interrupted. * Otherwise, if an interrupt is going to occur, bit0 of the
* If neither of these is the case, we wait for up to 50ms (badly I'm * SELECT register will be high, so we can set the handler the
* afraid!) until one of them is. * just return and be interrupted. If neither of these is the
*/ * case, we wait for up to 50ms (badly I'm afraid!) until one
* of them is.
*/
timeout = jiffies + HZ/20; /* 50ms wait */ timeout = jiffies + HZ/20; /* 50ms wait */
do { do {
if (!ata_status(drive, 0, DRQ_STAT)) { if (!ata_status(drive, 0, DRQ_STAT)) {
...@@ -646,11 +688,21 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -646,11 +688,21 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
return promise_read_intr(drive, rq); return promise_read_intr(drive, rq);
} }
if (inb(IDE_SELECT_REG) & 0x01) { if (inb(IDE_SELECT_REG) & 0x01) {
unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
#ifdef DEBUG_READ #ifdef DEBUG_READ
printk(KERN_DEBUG "%s: read: waiting for " printk(KERN_DEBUG "%s: read: waiting for "
"interrupt\n", drive->name); "interrupt\n", drive->name);
#endif #endif
ide_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
udelay(1); udelay(1);
......
...@@ -72,11 +72,6 @@ ...@@ -72,11 +72,6 @@
#define PIIX_CHECK_REV 0x40 /* May be a buggy revision of PIIX */ #define PIIX_CHECK_REV 0x40 /* May be a buggy revision of PIIX */
#define PIIX_NODMA 0x80 /* Don't do DMA with this chip */ #define PIIX_NODMA 0x80 /* Don't do DMA with this chip */
#ifdef CONFIG_BLK_DEV_PIIX_TRY133 /* I think even the older ICHs should be able to do UDMA133 */
#undef PIIX_UDMA_100
#define PIIX_UDMA_100 PIIX_UDMA_133
#endif
/* /*
* Intel IDE chips * Intel IDE chips
*/ */
...@@ -104,7 +99,6 @@ static struct piix_ide_chip { ...@@ -104,7 +99,6 @@ static struct piix_ide_chip {
static struct piix_ide_chip *piix_config; static struct piix_ide_chip *piix_config;
static unsigned char piix_enabled; static unsigned char piix_enabled;
static unsigned int piix_80w;
static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
......
...@@ -432,8 +432,8 @@ static unsigned int __init svwks_init_chipset(struct pci_dev *dev) ...@@ -432,8 +432,8 @@ static unsigned int __init svwks_init_chipset(struct pci_dev *dev)
return 0; return 0;
} }
/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem /* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
* device ID indicate presence of an 80-pin cable. * of the subsystem device ID indicate presence of an 80-pin cable.
* Bit 15 clear = secondary IDE channel does not have 80-pin cable. * Bit 15 clear = secondary IDE channel does not have 80-pin cable.
* Bit 15 set = secondary IDE channel has 80-pin cable. * Bit 15 set = secondary IDE channel has 80-pin cable.
* Bit 14 clear = primary IDE channel does not have 80-pin cable. * Bit 14 clear = primary IDE channel does not have 80-pin cable.
...@@ -444,7 +444,8 @@ static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif) ...@@ -444,7 +444,8 @@ static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif)
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS && dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
return ((1 << (hwif->unit + 14)) & return ((1 << (hwif->unit + 14)) &
dev->subsystem_device) ? 1 : 0; dev->subsystem_device) ? 1 : 0;
return 0; return 0;
......
...@@ -58,11 +58,18 @@ static ide_startstop_t service(struct ata_device *drive, struct request *rq); ...@@ -58,11 +58,18 @@ static ide_startstop_t service(struct ata_device *drive, struct request *rq);
static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq) static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq)
{ {
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
unsigned long flags;
ide__sti(); ide__sti();
spin_lock_irqsave(drive->channel->lock, flags);
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
drive->rq = NULL; drive->rq = NULL;
end_that_request_last(rq); end_that_request_last(rq);
spin_unlock_irqrestore(drive->channel->lock, flags);
kfree(args); kfree(args);
return ide_stopped; return ide_stopped;
...@@ -218,6 +225,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request * ...@@ -218,6 +225,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
* and it must have reported a need for service (status has SERVICE_STAT set) * and it must have reported a need for service (status has SERVICE_STAT set)
* *
* Also, nIEN must be set as not to need protection against ide_dmaq_intr * Also, nIEN must be set as not to need protection against ide_dmaq_intr
*
* Channel lock should be held.
*/ */
static ide_startstop_t service(struct ata_device *drive, struct request *rq) static ide_startstop_t service(struct ata_device *drive, struct request *rq)
{ {
...@@ -503,6 +512,8 @@ static int tcq_wait_dataphase(struct ata_device *drive) ...@@ -503,6 +512,8 @@ static int tcq_wait_dataphase(struct ata_device *drive)
/* /*
* Invoked from a SERVICE interrupt, command etc already known. Just need to * Invoked from a SERVICE interrupt, command etc already known. Just need to
* start the dma engine for this tag. * start the dma engine for this tag.
*
* Channel lock should be held.
*/ */
static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq) static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq)
{ {
...@@ -527,6 +538,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request * ...@@ -527,6 +538,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
/* /*
* Start a queued command from scratch. * Start a queued command from scratch.
*
* Channel lock should be held.
*/ */
ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq) ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq)
{ {
......
...@@ -223,15 +223,15 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq) ...@@ -223,15 +223,15 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq)
} }
trm290_prepare_drive(drive, 1); /* select DMA xfer */ trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(ch->dmatable_dma|reading|writing, ch->dma_base); outl(ch->dmatable_dma|reading|writing, ch->dma_base);
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
outw((count * 2) - 1, ch->dma_base+2); /* start DMA */ outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type != ATA_DISK) if (drive->type == ATA_DISK) {
return 0; ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL);
outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); }
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0; return 0;
} }
......
...@@ -243,7 +243,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int ...@@ -243,7 +243,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int
u8 *scsi_buf; u8 *scsi_buf;
unsigned long flags; unsigned long flags;
if (!(rq->flags & REQ_SPECIAL)) { if (!(rq->flags & REQ_PC)) {
ide_end_request(drive, rq, uptodate); ide_end_request(drive, rq, uptodate);
return 0; return 0;
} }
...@@ -293,6 +293,8 @@ static inline unsigned long get_timeout(struct atapi_packet_command *pc) ...@@ -293,6 +293,8 @@ static inline unsigned long get_timeout(struct atapi_packet_command *pc)
*/ */
static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
struct Scsi_Host *host = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host); idescsi_scsi_t *scsi = idescsi_private(host);
u8 ireason; u8 ireason;
...@@ -333,6 +335,8 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request ...@@ -333,6 +335,8 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request
temp = pc->actually_transferred + bcount; temp = pc->actually_transferred + bcount;
if ( temp > pc->request_transfer) { if ( temp > pc->request_transfer) {
if (temp > pc->buffer_size) { if (temp > pc->buffer_size) {
unsigned long flags;
struct ata_channel *ch = drive->channel;
printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n"); printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n");
temp = pc->buffer_size - pc->actually_transferred; temp = pc->buffer_size - pc->actually_transferred;
if (temp) { if (temp) {
...@@ -346,7 +350,14 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request ...@@ -346,7 +350,14 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request
pc->actually_transferred += temp; pc->actually_transferred += temp;
pc->current_position += temp; pc->current_position += temp;
atapi_discard_data(drive,bcount - temp); atapi_discard_data(drive,bcount - temp);
ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
#ifdef DEBUG #ifdef DEBUG
...@@ -370,12 +381,21 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request ...@@ -370,12 +381,21 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request
pc->actually_transferred+=bcount; /* Update the current position */ pc->actually_transferred+=bcount; /* Update the current position */
pc->current_position+=bcount; pc->current_position+=bcount;
ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq) static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
struct Scsi_Host *host = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host); idescsi_scsi_t *scsi = idescsi_private(host);
struct atapi_packet_command *pc = scsi->pc; struct atapi_packet_command *pc = scsi->pc;
...@@ -391,7 +411,15 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ ...@@ -391,7 +411,15 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ
printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped; return ide_stopped;
} }
ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */
spin_unlock_irqrestore(ch->lock, flags);
atapi_write(drive, scsi->pc->c, 12); /* Send the actual packet */ atapi_write(drive, scsi->pc->c, 12); /* Send the actual packet */
return ide_started; return ide_started;
} }
...@@ -425,8 +453,18 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request ...@@ -425,8 +453,18 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
set_bit(PC_DMA_IN_PROGRESS, &pc->flags); set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
udma_start(drive, rq); udma_start(drive, rq);
} }
if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
ide_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL);
spin_unlock_irqrestore(ch->lock, flags);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
return ide_started; return ide_started;
} else { } else {
...@@ -452,7 +490,7 @@ static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct reque ...@@ -452,7 +490,7 @@ static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct reque
rq->current_nr_sectors); rq->current_nr_sectors);
#endif #endif
if (rq->flags & REQ_SPECIAL) { if (rq->flags & REQ_PC) {
return idescsi_issue_pc(drive, rq, (struct atapi_packet_command *) rq->special); return idescsi_issue_pc(drive, rq, (struct atapi_packet_command *) rq->special);
} }
blk_dump_rq_flags(rq, "ide-scsi: unsup command"); blk_dump_rq_flags(rq, "ide-scsi: unsup command");
...@@ -667,7 +705,7 @@ static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ...@@ -667,7 +705,7 @@ static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
} }
memset(rq, 0, sizeof(*rq)); memset(rq, 0, sizeof(*rq));
rq->flags = REQ_SPECIAL; rq->flags = REQ_PC;
rq->special = (char *) pc; rq->special = (char *) pc;
rq->bio = idescsi_dma_bio (drive, pc); rq->bio = idescsi_dma_bio (drive, pc);
spin_unlock_irq(cmd->host->host_lock); spin_unlock_irq(cmd->host->host_lock);
......
...@@ -213,6 +213,7 @@ void ide_setup_ports(hw_regs_t *hw, ...@@ -213,6 +213,7 @@ void ide_setup_ports(hw_regs_t *hw,
/* Currently only m68k, apus and m8xx need it */ /* Currently only m68k, apus and m8xx need it */
#ifdef ATA_ARCH_ACK_INTR #ifdef ATA_ARCH_ACK_INTR
extern int ide_irq_lock;
# define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) # define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1)
#else #else
# define ide_ack_intr(hwif) (1) # define ide_ack_intr(hwif) (1)
...@@ -603,11 +604,7 @@ extern int noautodma; ...@@ -603,11 +604,7 @@ extern int noautodma;
extern int __ide_end_request(struct ata_device *, struct request *, int, unsigned int); extern int __ide_end_request(struct ata_device *, struct request *, int, unsigned int);
extern int ide_end_request(struct ata_device *drive, struct request *, int); extern int ide_end_request(struct ata_device *drive, struct request *, int);
/* extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
* This is used on exit from the driver, to designate the next irq handler
* and also to start the safety timer.
*/
extern void ide_set_handler(struct ata_device *drive, ata_handler_t handler,
unsigned long timeout, ata_expiry_t expiry); unsigned long timeout, ata_expiry_t expiry);
extern u8 ata_dump(struct ata_device *, struct request *, const char *); extern u8 ata_dump(struct ata_device *, struct request *, const char *);
......
...@@ -1111,6 +1111,7 @@ ...@@ -1111,6 +1111,7 @@
#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB #define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230 #define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
......
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