Commit 5be8243b authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.7 IDE 28a

- Apply Pavel Macheks suspend resume double resume fix.

- Finally remove the busy field for ata_operations and replace it with
   MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT.

- Fix ali15xx chipset support by removing initialization differences,
   apparently caused by mislead interpretation of the specs or a mismatch
   between the specification and reality.

- Guard calls to ide_set_handler with checks to see whatever the previously
   installed IRQ handler already served it's purpose.

- Convert timeout checks on poll_timeout to the time_before() interface.

- Consolidate the two different IRQ handlers for multi mode PIO writes into
   one. The problems remain the same but at least now we will only have to
   tangle one single problem.
parent ff3c2cbb
......@@ -798,7 +798,7 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
* not a diskdrive.
*/
if (drive->media != ide_disk)
if (drive->type != ATA_DISK)
return 0;
dma_begin:
......@@ -809,7 +809,7 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
WAIT_DMA(ATA_RX_DMA_NBR);
/* set up the Etrax DMA descriptors */
if(e100_ide_build_dmatable (drive))
return 1;
......
......@@ -334,6 +334,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0;
......
......@@ -441,9 +441,10 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
: DMA_MODE_WRITE);
drive->waiting_for_dma = 1;
if (drive->media != ide_disk)
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA,
IDE_COMMAND_REG);
......
......@@ -740,11 +740,12 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
if (IDE_CONTROL_REG)
OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
if (info->dma)
(void) drive->channel->dmaproc(ide_dma_begin, drive);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
return ide_started;
......@@ -787,6 +788,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
}
/* Arm the interrupt handler. */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
/* Send the command to the device. */
......@@ -1005,7 +1007,9 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
/* Done moving data!
Wait for another interrupt. */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
return ide_started;
}
......@@ -1335,6 +1339,8 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
}
/* Now we wait for another interrupt. */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
return ide_started;
}
......@@ -1559,6 +1565,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
}
/* re-arm handler */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
return ide_started;
}
......@@ -2984,15 +2991,14 @@ int ide_cdrom_init(void)
memset (info, 0, sizeof (struct cdrom_info));
drive->driver_data = info;
/* ATA-PATTERN */
ata_ops(drive)->busy++;
MOD_INC_USE_COUNT;
if (ide_cdrom_setup (drive)) {
ata_ops(drive)->busy--;
MOD_DEC_USE_COUNT;
if (ide_cdrom_cleanup (drive))
printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
continue;
}
ata_ops(drive)->busy--;
MOD_DEC_USE_COUNT;
failed--;
}
......
......@@ -323,7 +323,7 @@ static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq
while (drive->blocked) {
yield();
// panic("ide: Request while drive blocked?");
printk("ide: Request while drive blocked?");
}
if (!(rq->flags & REQ_CMD)) {
......@@ -380,12 +380,14 @@ static int idedisk_flushcache(ide_drive_t *drive)
{
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
if (drive->id->cfs_enable_2 & 0x2400)
taskfile.command = WIN_FLUSH_CACHE_EXT;
else
taskfile.command = WIN_FLUSH_CACHE;
return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
}
......@@ -504,7 +506,7 @@ static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long a
args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40;
args.taskfile.command = WIN_SET_MAX;
args.handler = task_no_data_intr;
args.handler = task_no_data_intr;
/* submit command request */
ide_raw_taskfile(drive, &args, NULL);
/* if OK, read new maximum address value */
......@@ -540,7 +542,7 @@ static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsign
args.hobfile.device_head = 0x40;
args.hobfile.control = (drive->ctl | 0x80);
args.handler = task_no_data_intr;
args.handler = task_no_data_intr;
/* submit command request */
ide_raw_taskfile(drive, &args, NULL);
/* if OK, compute maximum address value */
......@@ -611,10 +613,10 @@ static void init_idedisk_capacity (ide_drive_t *drive)
drive->select.b.lba = 1;
drive->id->lba_capacity_2 = capacity_2;
}
#else /* !CONFIG_IDEDISK_STROKE */
#else
printk("%s: setmax_ext LBA %llu, native %llu\n",
drive->name, set_max_ext, capacity_2);
#endif /* CONFIG_IDEDISK_STROKE */
#endif
}
drive->bios_cyl = drive->cyl;
drive->capacity48 = capacity_2;
......@@ -637,10 +639,10 @@ static void init_idedisk_capacity (ide_drive_t *drive)
drive->select.b.lba = 1;
drive->id->lba_capacity = capacity;
}
#else /* !CONFIG_IDEDISK_STROKE */
#else
printk("%s: setmax LBA %lu, native %lu\n",
drive->name, set_max, capacity);
#endif /* CONFIG_IDEDISK_STROKE */
#endif
}
drive->capacity = capacity;
......@@ -954,6 +956,9 @@ static int idedisk_suspend(struct device *dev, u32 state, u32 level)
* already been done...
*/
if (level != SUSPEND_SAVE_STATE)
return 0;
/* wait until all commands are finished */
printk("ide_disk_suspend()\n");
while (HWGROUP(drive)->handler)
......@@ -973,6 +978,9 @@ static int idedisk_suspend(struct device *dev, u32 state, u32 level)
static int idedisk_resume(struct device *dev, u32 level)
{
ide_drive_t *drive = dev->driver_data;
if (level != RESUME_RESTORE_STATE)
return 0;
if (!drive->blocked)
panic("ide: Resume but not suspended?\n");
......@@ -1113,8 +1121,11 @@ static void idedisk_setup(ide_drive_t *drive)
(void) probe_lba_addressing(drive, 1);
}
static int idedisk_cleanup (ide_drive_t *drive)
static int idedisk_cleanup(ide_drive_t *drive)
{
if (!drive)
return 0;
put_device(&drive->device);
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
if (idedisk_flushcache(drive))
......
......@@ -588,6 +588,8 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
(drive->addressing == 1)) {
......
......@@ -968,6 +968,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n");
idefloppy_discard_data (drive,bcount.all);
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
return ide_started;
}
......@@ -990,7 +991,9 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
pc->actually_transferred+=bcount.all; /* Update the current position */
pc->current_position+=bcount.all;
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
return ide_started;
}
......@@ -1014,8 +1017,11 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped;
}
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
return ide_started;
}
......@@ -1055,17 +1061,19 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped;
}
/*
/*
* The following delay solves a problem with ATAPI Zip 100 drives where the
* Busy flag was apparently being deasserted before the unit was ready to
* receive data. This was happening on a 1200 MHz Athlon system. 10/26/01
* 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will
* 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will
* not be actually used until after the packet is moved in about 50 msec.
*/
ide_set_handler (drive,
&idefloppy_pc_intr, /* service routine for packet command */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive,
&idefloppy_pc_intr, /* service routine for packet command */
floppy->ticks, /* wait this long before "failing" */
&idefloppy_transfer_pc2); /* fail == transfer_pc2 */
return ide_started;
}
......@@ -1143,8 +1151,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
} else {
pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */
}
if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
return ide_started;
......@@ -1156,7 +1165,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
static void idefloppy_rw_callback (ide_drive_t *drive)
{
#if IDEFLOPPY_DEBUG_LOG
#if IDEFLOPPY_DEBUG_LOG
printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
#endif /* IDEFLOPPY_DEBUG_LOG */
......@@ -2109,10 +2118,9 @@ int idefloppy_init (void)
kfree (floppy);
continue;
}
/* ATA-PATTERN */
ata_ops(drive)->busy++;
MOD_INC_USE_COUNT;
idefloppy_setup (drive, floppy);
ata_ops(drive)->busy--;
MOD_DEC_USE_COUNT;
failed--;
}
......
......@@ -931,12 +931,12 @@ pmac_ide_check_dma(ide_drive_t *drive)
int enable = 1;
drive->using_dma = 0;
idx = pmac_ide_find(drive);
if (idx < 0)
return 0;
if (drive->media == ide_floppy)
if (drive->type == ATA_FLOPPY)
enable = 0;
if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE))
enable = 0;
......@@ -945,9 +945,9 @@ pmac_ide_check_dma(ide_drive_t *drive)
udma = 0;
ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
if(enable) {
if (ata4 && (drive->media == ide_disk) &&
if (ata4 && (drive->type == ATA_DISK) &&
(id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
/* UltraDMA modes. */
drive->using_dma = pmac_ide_udma_enable(drive, idx);
......@@ -994,8 +994,9 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
return 1;
drive->waiting_for_dma = 1;
if (drive->media != ide_disk)
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA,
IDE_COMMAND_REG);
......@@ -1054,12 +1055,12 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
{
int j;
/* FIXME: We only handle the master IDE disk, we shoud
* try to fix CD-ROMs here
*/
switch (drive->media) {
case ide_disk:
switch (drive->type) {
case ATA_DISK:
/* Spin down the drive */
outb(0xa0, base+0x60);
outb(0x0, base+0x30);
......@@ -1067,7 +1068,7 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
outb(0x0, base+0x40);
outb(0x0, base+0x50);
outb(0xe0, base+0x70);
outb(0x2, base+0x160);
outb(0x2, base+0x160);
for (j = 0; j < 10; j++) {
int status;
mdelay(100);
......@@ -1076,10 +1077,10 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
break;
}
break;
case ide_cdrom:
case ATA_ROM:
// todo
break;
case ide_floppy:
case ATA_FLOPPY:
// todo
break;
}
......
......@@ -2155,7 +2155,8 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
idetape_discard_data (drive, bcount.all);
ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
return ide_started;
}
#if IDETAPE_DEBUG_LOG
......@@ -2181,7 +2182,8 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
#endif
ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */
return ide_started;
}
......@@ -2255,6 +2257,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
return ide_stopped;
}
tape->cmd_start_time = jiffies;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
return ide_started;
......@@ -2328,6 +2331,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
return ide_started;
......@@ -6099,8 +6103,7 @@ static int idetape_cleanup (ide_drive_t *drive)
idetape_chrdevs[minor].drive = NULL;
restore_flags (flags); /* all CPUs (overkill?) */
/* FIXME: this appears to be totally wrong! */
ata_ops(drive)->busy = 0;
MOD_DEC_USE_COUNT;
ide_unregister_subdriver (drive);
drive->driver_data = NULL;
......
......@@ -33,7 +33,7 @@
#define DEBUG_TASKFILE 0 /* unset when fixed */
#if DEBUG_TASKFILE
#define DTF(x...) printk(##x)
#define DTF(x...) printk(x)
#else
#define DTF(x...)
#endif
......@@ -55,7 +55,7 @@ static inline void ide_unmap_rq(struct request *rq, char *to,
unsigned long *flags)
{
if (rq->bio)
bio_kunmap_irq(to, flags);
bio_kunmap_irq(to, flags);
}
static void bswap_data (void *buffer, int wcount)
......@@ -288,73 +288,104 @@ void ata_poll_drive_ready(ide_drive_t *drive)
break;
}
}
static ide_startstop_t bio_mulout_intr(ide_drive_t *drive);
/*
* Handler for command write multiple
* Called directly from execute_drive_cmd for the first bunch of sectors,
* afterwards only by the ISR
*/
static ide_startstop_t task_mulout_intr(ide_drive_t *drive)
static ide_startstop_t pre_task_mulout_intr(ide_drive_t *drive, struct request *rq)
{
ide_task_t *args = rq->special;
ide_startstop_t startstop;
/*
* assign private copy for multi-write
*/
memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
return startstop;
ata_poll_drive_ready(drive);
return args->handler(drive);
}
static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
{
unsigned int msect, nsect;
byte stat = GET_STAT();
byte io_32bit = drive->io_32bit;
struct request *rq = HWGROUP(drive)->rq;
struct request *rq = &HWGROUP(drive)->wrq;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
char *pBuf = NULL;
unsigned long flags;
int mcount = drive->mult_count;
ide_startstop_t startstop;
/*
* (ks/hs): Handle last IRQ on multi-sector transfer,
* occurs after all data was sent in this chunk
*/
if (rq->current_nr_sectors == 0) {
if (stat & (ERR_STAT|DRQ_STAT))
return ide_error(drive, "task_mulout_intr", stat);
if (!rq->nr_sectors) {
if (stat & (ERR_STAT|DRQ_STAT)) {
startstop = ide_error(drive, "task_mulout_intr", stat);
memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
return startstop;
}
/*
* there may be more, ide_do_request will restart it if
* necessary
*/
ide_end_request(drive, 1);
__ide_end_request(drive, 1, rq->hard_nr_sectors);
rq->bio = NULL;
return ide_stopped;
}
if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT)) {
return ide_error(drive, "task_mulout_intr", stat);
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) {
startstop = ide_error(drive, "task_mulout_intr", stat);
memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
return startstop;
}
/* no data yet, so wait for another interrupt */
if (hwgroup->handler == NULL)
ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
return ide_started;
}
/* (ks/hs): See task_mulin_intr */
msect = drive->mult_count;
nsect = rq->current_nr_sectors;
if (nsect > msect)
nsect = msect;
do {
char *buffer;
int nsect = rq->current_nr_sectors;
unsigned long flags;
pBuf = ide_map_rq(rq, &flags);
DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
pBuf, nsect, rq->current_nr_sectors);
if (nsect > mcount)
nsect = mcount;
mcount -= nsect;
drive->io_32bit = 0;
taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
rq->sector += nsect;
rq->nr_sectors -= nsect;
rq->current_nr_sectors -= nsect;
ide_unmap_rq(rq, pBuf, &flags);
/* Do we move to the next bio after this? */
if (!rq->current_nr_sectors) {
/* remember to fix this up /jens */
struct bio *bio = rq->bio->bi_next;
drive->io_32bit = io_32bit;
/* end early if we ran out of requests */
if (!bio) {
mcount = 0;
} else {
rq->bio = bio;
rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
}
}
rq->errors = 0;
/* Are we sure that this as all been already transfered? */
rq->current_nr_sectors -= nsect;
/*
* Ok, we're all setup for the interrupt
* re-entering us on the last transfer.
*/
taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
bio_kunmap_irq(buffer, &flags);
} while (mcount);
drive->io_32bit = io_32bit;
rq->errors = 0;
if (hwgroup->handler == NULL)
ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
return ide_started;
}
......@@ -371,7 +402,7 @@ ide_startstop_t ata_taskfile(ide_drive_t *drive,
u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF;
/* (ks/hs): Moved to start, do not use for multiple out commands */
if (handler != task_mulout_intr && handler != bio_mulout_intr) {
if (handler != task_mulout_intr) {
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(drive->channel, drive, 0);
......@@ -583,107 +614,6 @@ static ide_startstop_t task_out_intr(ide_drive_t *drive)
return ide_started;
}
static ide_startstop_t pre_bio_out_intr(ide_drive_t *drive, struct request *rq)
{
ide_task_t *args = rq->special;
ide_startstop_t startstop;
/*
* assign private copy for multi-write
*/
memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
return startstop;
ata_poll_drive_ready(drive);
return args->handler(drive);
}
static ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
byte io_32bit = drive->io_32bit;
struct request *rq = &HWGROUP(drive)->wrq;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
int mcount = drive->mult_count;
ide_startstop_t startstop;
/*
* (ks/hs): Handle last IRQ on multi-sector transfer,
* occurs after all data was sent in this chunk
*/
if (!rq->nr_sectors) {
if (stat & (ERR_STAT|DRQ_STAT)) {
startstop = ide_error(drive, "bio_mulout_intr", stat);
memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
return startstop;
}
__ide_end_request(drive, 1, rq->hard_nr_sectors);
HWGROUP(drive)->wrq.bio = NULL;
return ide_stopped;
}
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) {
startstop = ide_error(drive, "bio_mulout_intr", stat);
memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
return startstop;
}
/* no data yet, so wait for another interrupt */
if (hwgroup->handler == NULL)
ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
return ide_started;
}
do {
char *buffer;
int nsect = rq->current_nr_sectors;
unsigned long flags;
if (nsect > mcount)
nsect = mcount;
mcount -= nsect;
buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
rq->sector += nsect;
rq->nr_sectors -= nsect;
rq->current_nr_sectors -= nsect;
/* Do we move to the next bio after this? */
if (!rq->current_nr_sectors) {
/* remember to fix this up /jens */
struct bio *bio = rq->bio->bi_next;
/* end early early we ran out of requests */
if (!bio) {
mcount = 0;
} else {
rq->bio = bio;
rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
}
}
/*
* Ok, we're all setup for the interrupt
* re-entering us on the last transfer.
*/
taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
bio_kunmap_irq(buffer, &flags);
} while (mcount);
drive->io_32bit = io_32bit;
rq->errors = 0;
if (hwgroup->handler == NULL)
ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
return ide_started;
}
/*
* Handler for command with Read Multiple
*/
......@@ -781,8 +711,8 @@ void ide_cmd_type_parser(ide_task_t *args)
case CFA_WRITE_MULTI_WO_ERASE:
case WIN_MULTWRITE:
case WIN_MULTWRITE_EXT:
args->prehandler = pre_bio_out_intr;
args->handler = bio_mulout_intr;
args->prehandler = pre_task_mulout_intr;
args->handler = task_mulout_intr;
args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
return;
......@@ -989,7 +919,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *args, byte *buf)
*
* The caller has to make sure buf is never NULL!
*/
static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *argbuf)
static int ide_wait_cmd(ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *argbuf)
{
struct request rq;
......@@ -998,10 +928,10 @@ static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int
memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * sectors);
ide_init_drive_cmd(&rq);
rq.buffer = argbuf;
*argbuf++ = cmd;
*argbuf++ = nsect;
*argbuf++ = feature;
*argbuf++ = sectors;
argbuf[0] = cmd;
argbuf[1] = nsect;
argbuf[2] = feature;
argbuf[3] = sectors;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
......@@ -1009,7 +939,8 @@ static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int
int ide_cmd_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int err = 0;
byte args[4], *argbuf = args;
u8 args[4];
u8 *argbuf = args;
byte xfer_rate = 0;
int argsize = 4;
ide_task_t tfargs;
......
......@@ -548,7 +548,8 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
printk("%s: ATAPI reset complete\n", drive->name);
} else {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
return ide_started; /* continue polling */
}
......@@ -573,7 +574,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
byte tmp;
if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
return ide_started; /* continue polling */
}
......@@ -645,6 +647,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
udelay (20);
OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
__restore_flags (flags); /* local CPU only */
return ide_started;
......@@ -679,7 +682,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
}
udelay(10); /* more than enough time */
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/*
* Some weird controller like resetting themselves to a strange
......@@ -931,6 +935,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
*/
void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
{
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, handler, WAIT_CMD, NULL);
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
......@@ -1553,7 +1558,7 @@ static void unexpected_intr(int irq, ide_hwgroup_t *hwgroup)
/*
* entry point for all interrupts, caller does __cli() for us
*/
void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
void ide_intr(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
......@@ -1596,7 +1601,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
* Whack the status register, just in case we have a leftover pending IRQ.
*/
IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
#endif /* CONFIG_BLK_DEV_IDEPCI */
#endif
}
goto out_lock;
}
......@@ -3175,10 +3180,19 @@ int ide_unregister_subdriver(ide_drive_t *drive)
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
if (drive->usage || drive->busy || !ata_ops(drive) || ata_ops(drive)->busy) {
#if 0
if (__MOD_IN_USE(ata_ops(drive)->owner)) {
restore_flags(flags);
return 1;
}
#endif
if (drive->usage || drive->busy || !ata_ops(drive)) {
restore_flags(flags); /* all CPUs */
return 1;
}
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
pnpide_init(0);
#endif
......@@ -3189,7 +3203,10 @@ int ide_unregister_subdriver(ide_drive_t *drive)
#endif
auto_remove_settings(drive);
drive->driver = NULL;
drive->present = 0;
restore_flags(flags); /* all CPUs */
return 0;
}
......@@ -3298,6 +3315,7 @@ static int ide_notify_reboot (struct notifier_block *this, unsigned long event,
hwif = &ide_hwifs[i];
if (!hwif->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
if (!drive->present)
......
......@@ -394,6 +394,7 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
if (GET_STAT() & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */
}
......@@ -476,6 +477,7 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */
}
......@@ -489,6 +491,7 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
*/
promise_multwrite(drive, 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
......@@ -523,6 +526,7 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if (promise_multwrite(drive, rq->nr_sectors - 4))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
return ide_started;
} else {
......@@ -533,6 +537,7 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if (promise_multwrite(drive, rq->nr_sectors))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
......@@ -554,6 +559,13 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
unsigned long timeout;
byte stat;
/* Check that it's a regular command. If not, bomb out early. */
if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "pdc4030 bad flags");
ide_end_request(drive, 0);
return ide_stopped;
}
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(drive->channel, drive, 0);
......@@ -568,20 +580,12 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
OUT_BYTE(taskfile->device_head, IDE_SELECT_REG);
OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
/* Check that it's a regular command. If not, bomb out early. */
if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "pdc4030 bad flags");
ide_end_request(drive, 0);
return ide_stopped;
}
switch (rq_data_dir(rq)) {
case READ:
OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
/*
* The card's behaviour is odd at this point. If the data is
* available, DRQ will be true, and no interrupt will be
* generated by the card. If this is the case, we need to call the
* generated by the card. If this is the case, we need to call the
* "interrupt" handler (promise_read_intr) directly. Otherwise, if
* an interrupt is going to occur, bit0 of the SELECT register will
* be high, so we can set the handler the just return and be interrupted.
......@@ -600,6 +604,7 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
printk(KERN_DEBUG "%s: read: waiting for "
"interrupt\n", drive->name);
#endif
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
return ide_started;
}
......@@ -612,7 +617,6 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
case WRITE: {
ide_startstop_t startstop;
OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
/*
* Strategy on write is:
* look for the DRQ that should have been immediately asserted
......@@ -624,7 +628,7 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
printk(KERN_ERR "%s: no DRQ after issuing "
"PROMISE_WRITE\n", drive->name);
return startstop;
}
}
if (!drive->unmask)
__cli(); /* local CPU only */
HWGROUP(drive)->wrq = *rq; /* scratchpad */
......
......@@ -194,6 +194,7 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0;
......
......@@ -508,7 +508,7 @@ static void idescsi_add_settings(ide_drive_t *drive)
*/
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id)
{
ata_ops(drive)->busy++;
MOD_INC_USE_COUNT;
idescsi_drives[id] = drive;
drive->driver_data = scsi;
......@@ -629,8 +629,9 @@ int idescsi_release (struct Scsi_Host *host)
for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
drive = idescsi_drives[id];
if (drive)
ata_ops(drive)->busy--;
if (drive) {
MOD_DEC_USE_COUNT;
}
}
return 0;
}
......
......@@ -300,10 +300,13 @@ typedef struct ide_drive_s {
byte slow; /* flag: slow data port */
byte bswap; /* flag: byte swap data */
byte dsc_overlap; /* flag: DSC overlap */
unsigned waiting_for_dma: 1; /* dma currently in progress */
unsigned busy : 1; /* currently doing revalidate_disk() */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
unsigned present : 1; /* drive is physically present */
unsigned noprobe : 1; /* from: hdx=noprobe */
unsigned busy : 1; /* currently doing revalidate_disk() */
unsigned removable : 1; /* 1 if need to do check_media_change */
unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */
unsigned no_unmask : 1; /* disallow setting unmask bit */
......@@ -315,7 +318,6 @@ typedef struct ide_drive_s {
unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */
unsigned ata_flash : 1; /* 1=present, 0=default */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */
byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
select_t select; /* basic drive/head select reg value */
......@@ -620,7 +622,6 @@ read_proc_t proc_ide_read_geometry;
struct ata_operations {
struct module *owner;
unsigned busy: 1; /* FIXME: this will go soon away... */
int (*cleanup)(ide_drive_t *);
int (*standby)(ide_drive_t *);
ide_startstop_t (*do_request)(ide_drive_t *, struct request *, unsigned long);
......@@ -635,6 +636,7 @@ struct ata_operations {
void (*pre_reset)(ide_drive_t *);
unsigned long (*capacity)(ide_drive_t *);
ide_startstop_t (*special)(ide_drive_t *);
ide_proc_entry_t *proc;
};
......
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