diff -urN linux-2.5.7/arch/cris/drivers/ide.c linux/arch/cris/drivers/ide.c --- linux-2.5.7/arch/cris/drivers/ide.c Thu Mar 28 06:59:54 2002 +++ linux/arch/cris/drivers/ide.c Wed Mar 27 02:47:13 2002 @@ -798,7 +798,7 @@ * not a diskdrive. */ - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return 0; dma_begin: @@ -809,7 +809,7 @@ WAIT_DMA(ATA_RX_DMA_NBR); /* set up the Etrax DMA descriptors */ - + if(e100_ide_build_dmatable (drive)) return 1; diff -urN linux-2.5.7/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c --- linux-2.5.7/drivers/ide/hpt34x.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/ide/hpt34x.c Wed Mar 27 02:47:13 2002 @@ -334,6 +334,7 @@ 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; diff -urN linux-2.5.7/drivers/ide/icside.c linux/drivers/ide/icside.c --- linux-2.5.7/drivers/ide/icside.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/icside.c Wed Mar 27 02:47:13 2002 @@ -441,9 +441,10 @@ : 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); diff -urN linux-2.5.7/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c --- linux-2.5.7/drivers/ide/ide-cd.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/ide/ide-cd.c Wed Mar 27 02:47:13 2002 @@ -740,11 +740,12 @@ 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 @@ } /* 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 @@ /* 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 @@ } /* 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 @@ } /* 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 @@ 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--; } diff -urN linux-2.5.7/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c --- linux-2.5.7/drivers/ide/ide-disk.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/ide-disk.c Wed Mar 27 02:48:05 2002 @@ -323,7 +323,7 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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_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 @@ (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)) diff -urN linux-2.5.7/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c --- linux-2.5.7/drivers/ide/ide-dma.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/ide-dma.c Wed Mar 27 02:47:13 2002 @@ -588,6 +588,8 @@ 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)) { diff -urN linux-2.5.7/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c --- linux-2.5.7/drivers/ide/ide-floppy.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/ide/ide-floppy.c Wed Mar 27 02:47:13 2002 @@ -968,6 +968,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 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 @@ 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--; } diff -urN linux-2.5.7/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c --- linux-2.5.7/drivers/ide/ide-pmac.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/ide/ide-pmac.c Wed Mar 27 02:47:13 2002 @@ -931,12 +931,12 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ break; } break; - case ide_cdrom: + case ATA_ROM: // todo break; - case ide_floppy: + case ATA_FLOPPY: // todo break; } diff -urN linux-2.5.7/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c --- linux-2.5.7/drivers/ide/ide-tape.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/ide-tape.c Wed Mar 27 02:47:13 2002 @@ -2155,7 +2155,8 @@ 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 @@ 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 @@ 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 @@ } #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 @@ 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; diff -urN linux-2.5.7/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c --- linux-2.5.7/drivers/ide/ide-taskfile.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/ide/ide-taskfile.c Thu Mar 28 06:18:08 2002 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * * 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 @@ 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 @@ 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; diff -urN linux-2.5.7/drivers/ide/ide.c linux/drivers/ide/ide.c --- linux-2.5.7/drivers/ide/ide.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/ide.c Wed Mar 27 02:47:13 2002 @@ -548,7 +548,8 @@ 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 @@ 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 @@ 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 @@ } 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 @@ */ 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 @@ /* * 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 @@ * 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 @@ 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 @@ #endif auto_remove_settings(drive); drive->driver = NULL; + drive->present = 0; + restore_flags(flags); /* all CPUs */ + return 0; } @@ -3298,6 +3315,7 @@ hwif = &ide_hwifs[i]; if (!hwif->present) continue; + for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) diff -urN linux-2.5.7/drivers/ide/pdc4030.c linux/drivers/ide/pdc4030.c --- linux-2.5.7/drivers/ide/pdc4030.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/pdc4030.c Thu Mar 28 05:42:44 2002 @@ -394,6 +394,7 @@ 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 @@ 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 @@ */ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 */ diff -urN linux-2.5.7/drivers/ide/trm290.c linux/drivers/ide/trm290.c --- linux-2.5.7/drivers/ide/trm290.c Thu Mar 28 06:59:56 2002 +++ linux/drivers/ide/trm290.c Wed Mar 27 02:47:13 2002 @@ -194,6 +194,7 @@ 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; diff -urN linux-2.5.7/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- linux-2.5.7/drivers/scsi/ide-scsi.c Thu Mar 28 06:59:54 2002 +++ linux/drivers/scsi/ide-scsi.c Wed Mar 27 02:47:13 2002 @@ -508,7 +508,7 @@ */ 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 @@ 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; } diff -urN linux-2.5.7/include/linux/ide.h linux/include/linux/ide.h --- linux-2.5.7/include/linux/ide.h Thu Mar 28 06:59:56 2002 +++ linux/include/linux/ide.h Thu Mar 28 05:42:51 2002 @@ -300,10 +300,13 @@ 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 @@ 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 @@ 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 @@ void (*pre_reset)(ide_drive_t *); unsigned long (*capacity)(ide_drive_t *); ide_startstop_t (*special)(ide_drive_t *); + ide_proc_entry_t *proc; };