diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-16 11:07:59 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-16 11:07:59 +1000 |
commit | 84c3d4aaec3338201b449034beac41635866bddf (patch) | |
tree | 3412951682fb2dd4feb8a5532f8efbaf8b345933 /drivers/ide/ide-tape.c | |
parent | 43d2548bb2ef7e6d753f91468a746784041e522d (diff) | |
parent | fafa3a3f16723997f039a0193997464d66dafd8f (diff) |
Merge commit 'origin/master'
Manual merge of:
arch/powerpc/Kconfig
arch/powerpc/kernel/stacktrace.c
arch/powerpc/mm/slice.c
arch/ppc/kernel/smp.c
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r-- | drivers/ide/ide-tape.c | 561 |
1 files changed, 158 insertions, 403 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index a3d228302d2..f9cf1670e4e 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -144,9 +144,6 @@ enum { /*************************** End of tunable parameters ***********************/ -/* Read/Write error simulation */ -#define SIMULATE_ERRORS 0 - /* tape directions */ enum { IDETAPE_DIR_NONE = (1 << 0), @@ -442,7 +439,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, } } -static void idetape_update_buffers(struct ide_atapi_pc *pc) +static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct idetape_bh *bh = pc->bh; int count; @@ -506,18 +503,6 @@ static struct request *idetape_next_rq_storage(ide_drive_t *drive) return (&tape->rq_stack[tape->rq_stack_index++]); } -static void idetape_init_pc(struct ide_atapi_pc *pc) -{ - memset(pc->c, 0, 12); - pc->retries = 0; - pc->flags = 0; - pc->req_xfer = 0; - pc->buf = pc->pc_buf; - pc->buf_size = IDETAPE_PC_BUFFER_SIZE; - pc->bh = NULL; - pc->b_data = NULL; -} - /* * called on each failed packet command retry to analyze the request sense. We * currently do not utilize this information. @@ -538,8 +523,8 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) if (pc->flags & PC_FLAG_DMA_ERROR) { pc->xferred = pc->req_xfer - tape->blk_size * - be32_to_cpu(get_unaligned((u32 *)&sense[3])); - idetape_update_buffers(pc); + get_unaligned_be32(&sense[3]); + idetape_update_buffers(drive, pc); } /* @@ -634,21 +619,78 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) return 0; } -static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive) +static void ide_tape_callback(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; + struct ide_atapi_pc *pc = tape->pc; + int uptodate = pc->error ? 0 : 1; debug_log(DBG_PROCS, "Enter %s\n", __func__); - if (!tape->pc->error) { - idetape_analyze_error(drive, tape->pc->buf); - idetape_end_request(drive, 1, 0); - } else { - printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - " - "Aborting request!\n"); - idetape_end_request(drive, 0, 0); + if (tape->failed_pc == pc) + tape->failed_pc = NULL; + + if (pc->c[0] == REQUEST_SENSE) { + if (uptodate) + idetape_analyze_error(drive, pc->buf); + else + printk(KERN_ERR "ide-tape: Error in REQUEST SENSE " + "itself - Aborting request!\n"); + } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { + struct request *rq = drive->hwif->hwgroup->rq; + int blocks = pc->xferred / tape->blk_size; + + tape->avg_size += blocks * tape->blk_size; + + if (time_after_eq(jiffies, tape->avg_time + HZ)) { + tape->avg_speed = tape->avg_size * HZ / + (jiffies - tape->avg_time) / 1024; + tape->avg_size = 0; + tape->avg_time = jiffies; + } + + tape->first_frame += blocks; + rq->current_nr_sectors -= blocks; + + if (pc->error) + uptodate = pc->error; + } else if (pc->c[0] == READ_POSITION && uptodate) { + u8 *readpos = tape->pc->buf; + + debug_log(DBG_SENSE, "BOP - %s\n", + (readpos[0] & 0x80) ? "Yes" : "No"); + debug_log(DBG_SENSE, "EOP - %s\n", + (readpos[0] & 0x40) ? "Yes" : "No"); + + if (readpos[0] & 0x4) { + printk(KERN_INFO "ide-tape: Block location is unknown" + "to the tape\n"); + clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); + uptodate = 0; + } else { + debug_log(DBG_SENSE, "Block Location - %u\n", + be32_to_cpu(*(u32 *)&readpos[4])); + + tape->partition = readpos[1]; + tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]); + set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); + } } - return ide_stopped; + + idetape_end_request(drive, uptodate, 0); +} + +static void idetape_init_pc(struct ide_atapi_pc *pc) +{ + memset(pc->c, 0, 12); + pc->retries = 0; + pc->flags = 0; + pc->req_xfer = 0; + pc->buf = pc->pc_buf; + pc->buf_size = IDETAPE_PC_BUFFER_SIZE; + pc->bh = NULL; + pc->b_data = NULL; + pc->callback = ide_tape_callback; } static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) @@ -657,7 +699,6 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) pc->c[0] = REQUEST_SENSE; pc->c[4] = 20; pc->req_xfer = 20; - pc->idetape_callback = &idetape_request_sense_callback; } static void idetape_init_rq(struct request *rq, u8 cmd) @@ -688,9 +729,10 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, struct ide_tape_obj *tape = drive->driver_data; idetape_init_rq(rq, REQ_IDETAPE_PC1); + rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *) pc; rq->rq_disk = tape->disk; - (void) ide_do_drive_cmd(drive, rq, ide_preempt); + ide_do_drive_cmd(drive, rq); } /* @@ -698,7 +740,7 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, * last packet command. We queue a request sense packet command in * the head of the request list. */ -static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) +static void idetape_retry_pc(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; struct ide_atapi_pc *pc; @@ -710,7 +752,6 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) idetape_create_request_sense_cmd(pc); set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags); idetape_queue_pc_head(drive, pc, rq); - return ide_stopped; } /* @@ -727,7 +768,26 @@ static void idetape_postpone_request(ide_drive_t *drive) ide_stall_queue(drive, tape->dsc_poll_freq); } -typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int); +static void ide_tape_handle_dsc(ide_drive_t *drive) +{ + idetape_tape_t *tape = drive->driver_data; + + /* Media access command */ + tape->dsc_polling_start = jiffies; + tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST; + tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; + /* Allow ide.c to handle other requests */ + idetape_postpone_request(drive); +} + +static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount, int write) +{ + if (write) + idetape_output_buffers(drive, pc, bcount); + else + idetape_input_buffers(drive, pc, bcount); +} /* * This is the usual interrupt handler which will be called during a packet @@ -738,169 +798,11 @@ typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int); */ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - struct ide_atapi_pc *pc = tape->pc; - xfer_func_t *xferfunc; - idetape_io_buf *iobuf; - unsigned int temp; -#if SIMULATE_ERRORS - static int error_sim_count; -#endif - u16 bcount; - u8 stat, ireason; - - debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__); - - /* Clear the interrupt */ - stat = ide_read_status(drive); - - if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { - if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) { - /* - * A DMA error is sometimes expected. For example, - * if the tape is crossing a filemark during a - * READ command, it will issue an irq and position - * itself before the filemark, so that only a partial - * data transfer will occur (which causes the DMA - * error). In that case, we will later ask the tape - * how much bytes of the original request were - * actually transferred (we can't receive that - * information from the DMA engine on most chipsets). - */ - - /* - * On the contrary, a DMA error is never expected; - * it usually indicates a hardware error or abort. - * If the tape crosses a filemark during a READ - * command, it will issue an irq and position itself - * after the filemark (not before). Only a partial - * data transfer will occur, but no DMA error. - * (AS, 19 Apr 2001) - */ - pc->flags |= PC_FLAG_DMA_ERROR; - } else { - pc->xferred = pc->req_xfer; - idetape_update_buffers(pc); - } - debug_log(DBG_PROCS, "DMA finished\n"); - - } - - /* No more interrupts */ - if ((stat & DRQ_STAT) == 0) { - debug_log(DBG_SENSE, "Packet command completed, %d bytes" - " transferred\n", pc->xferred); - - pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; - local_irq_enable(); - -#if SIMULATE_ERRORS - if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) && - (++error_sim_count % 100) == 0) { - printk(KERN_INFO "ide-tape: %s: simulating error\n", - tape->name); - stat |= ERR_STAT; - } -#endif - if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE) - stat &= ~ERR_STAT; - if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { - /* Error detected */ - debug_log(DBG_ERR, "%s: I/O error\n", tape->name); - - if (pc->c[0] == REQUEST_SENSE) { - printk(KERN_ERR "ide-tape: I/O error in request" - " sense command\n"); - return ide_do_reset(drive); - } - debug_log(DBG_ERR, "[cmd %x]: check condition\n", - pc->c[0]); - - /* Retry operation */ - return idetape_retry_pc(drive); - } - pc->error = 0; - if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && - (stat & SEEK_STAT) == 0) { - /* Media access command */ - tape->dsc_polling_start = jiffies; - tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST; - tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; - /* Allow ide.c to handle other requests */ - idetape_postpone_request(drive); - return ide_stopped; - } - if (tape->failed_pc == pc) - tape->failed_pc = NULL; - /* Command finished - Call the callback function */ - return pc->idetape_callback(drive); - } - - if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { - pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; - printk(KERN_ERR "ide-tape: The tape wants to issue more " - "interrupts in DMA mode\n"); - printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); - ide_dma_off(drive); - return ide_do_reset(drive); - } - /* Get the number of bytes to transfer on this interrupt. */ - bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | - hwif->INB(hwif->io_ports.lbam_addr); - - ireason = hwif->INB(hwif->io_ports.nsect_addr); - - if (ireason & CD) { - printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__); - return ide_do_reset(drive); - } - if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { - /* Hopefully, we will never get here */ - printk(KERN_ERR "ide-tape: We wanted to %s, ", - (ireason & IO) ? "Write" : "Read"); - printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n", - (ireason & IO) ? "Read" : "Write"); - return ide_do_reset(drive); - } - if (!(pc->flags & PC_FLAG_WRITING)) { - /* Reading - Check that we have enough space */ - temp = pc->xferred + bcount; - if (temp > pc->req_xfer) { - if (temp > pc->buf_size) { - printk(KERN_ERR "ide-tape: The tape wants to " - "send us more data than expected " - "- discarding data\n"); - ide_pad_transfer(drive, 0, bcount); - ide_set_handler(drive, &idetape_pc_intr, - IDETAPE_WAIT_CMD, NULL); - return ide_started; - } - debug_log(DBG_SENSE, "The tape wants to send us more " - "data than expected - allowing transfer\n"); - } - iobuf = &idetape_input_buffers; - xferfunc = hwif->input_data; - } else { - iobuf = &idetape_output_buffers; - xferfunc = hwif->output_data; - } - - if (pc->bh) - iobuf(drive, pc, bcount); - else - xferfunc(drive, NULL, pc->cur_pos, bcount); - - /* Update the current position */ - pc->xferred += bcount; - pc->cur_pos += bcount; - - debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n", - pc->c[0], bcount); - /* And set the interrupt handler again */ - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); - return ide_started; + return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD, + NULL, idetape_update_buffers, idetape_retry_pc, + ide_tape_handle_dsc, ide_tape_io_buffers); } /* @@ -941,56 +843,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) */ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - struct ide_atapi_pc *pc = tape->pc; - int retries = 100; - ide_startstop_t startstop; - u8 ireason; - - if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { - printk(KERN_ERR "ide-tape: Strange, packet command initiated " - "yet DRQ isn't asserted\n"); - return startstop; - } - ireason = hwif->INB(hwif->io_ports.nsect_addr); - while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing " - "a packet command, retrying\n"); - udelay(100); - ireason = hwif->INB(hwif->io_ports.nsect_addr); - if (retries == 0) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while " - "issuing a packet command, ignoring\n"); - ireason |= CD; - ireason &= ~IO; - } - } - if ((ireason & CD) == 0 || (ireason & IO)) { - printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing " - "a packet command\n"); - return ide_do_reset(drive); - } - /* Set the interrupt routine */ - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); -#ifdef CONFIG_BLK_DEV_IDEDMA - /* Begin DMA, if necessary */ - if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) - hwif->dma_ops->dma_start(drive); -#endif - /* Send the actual packet */ - hwif->output_data(drive, NULL, pc->c, 12); - return ide_started; + return ide_transfer_pc(drive, tape->pc, idetape_pc_intr, + IDETAPE_WAIT_CMD, NULL); } static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc) { - ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - int dma_ok = 0; - u16 bcount; if (tape->pc->c[0] == REQUEST_SENSE && pc->c[0] == REQUEST_SENSE) { @@ -1025,50 +887,15 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, pc->error = IDETAPE_ERROR_GENERAL; } tape->failed_pc = NULL; - return pc->idetape_callback(drive); + pc->callback(drive); + return ide_stopped; } debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); pc->retries++; - /* We haven't transferred any data yet */ - pc->xferred = 0; - pc->cur_pos = pc->buf; - /* Request to transfer the entire buffer at once */ - bcount = pc->req_xfer; - if (pc->flags & PC_FLAG_DMA_ERROR) { - pc->flags &= ~PC_FLAG_DMA_ERROR; - printk(KERN_WARNING "ide-tape: DMA disabled, " - "reverting to PIO\n"); - ide_dma_off(drive); - } - if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma) - dma_ok = !hwif->dma_ops->dma_setup(drive); - - ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK | - IDE_TFLAG_OUT_DEVICE, bcount, dma_ok); - - if (dma_ok) - /* Will begin DMA later */ - pc->flags |= PC_FLAG_DMA_IN_PROGRESS; - if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) { - ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc, - IDETAPE_WAIT_CMD, NULL); - return ide_started; - } else { - ide_execute_pkt_cmd(drive); - return idetape_transfer_pc(drive); - } -} - -static ide_startstop_t idetape_pc_callback(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - idetape_end_request(drive, tape->pc->error ? 0 : 1, 0); - return ide_stopped; + return ide_issue_pc(drive, pc, idetape_transfer_pc, + IDETAPE_WAIT_CMD, NULL); } /* A mode sense command is used to "sense" tape parameters. */ @@ -1096,7 +923,6 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) pc->req_xfer = 24; else pc->req_xfer = 50; - pc->idetape_callback = &idetape_pc_callback; } static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) @@ -1114,80 +940,41 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) printk(KERN_ERR "ide-tape: %s: I/O error, ", tape->name); /* Retry operation */ - return idetape_retry_pc(drive); + idetape_retry_pc(drive); + return ide_stopped; } pc->error = 0; - if (tape->failed_pc == pc) - tape->failed_pc = NULL; } else { pc->error = IDETAPE_ERROR_GENERAL; tape->failed_pc = NULL; } - return pc->idetape_callback(drive); -} - -static ide_startstop_t idetape_rw_callback(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - int blocks = tape->pc->xferred / tape->blk_size; - - tape->avg_size += blocks * tape->blk_size; - - if (time_after_eq(jiffies, tape->avg_time + HZ)) { - tape->avg_speed = tape->avg_size * HZ / - (jiffies - tape->avg_time) / 1024; - tape->avg_size = 0; - tape->avg_time = jiffies; - } - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - tape->first_frame += blocks; - rq->current_nr_sectors -= blocks; - - if (!tape->pc->error) - idetape_end_request(drive, 1, 0); - else - idetape_end_request(drive, tape->pc->error, 0); + pc->callback(drive); return ide_stopped; } -static void idetape_create_read_cmd(idetape_tape_t *tape, - struct ide_atapi_pc *pc, - unsigned int length, struct idetape_bh *bh) +static void ide_tape_create_rw_cmd(idetape_tape_t *tape, + struct ide_atapi_pc *pc, unsigned int length, + struct idetape_bh *bh, u8 opcode) { idetape_init_pc(pc); - pc->c[0] = READ_6; put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; - pc->idetape_callback = &idetape_rw_callback; pc->bh = bh; - atomic_set(&bh->b_count, 0); pc->buf = NULL; pc->buf_size = length * tape->blk_size; pc->req_xfer = pc->buf_size; if (pc->req_xfer == tape->buffer_size) - pc->flags |= PC_FLAG_DMA_RECOMMENDED; -} + pc->flags |= PC_FLAG_DMA_OK; -static void idetape_create_write_cmd(idetape_tape_t *tape, - struct ide_atapi_pc *pc, - unsigned int length, struct idetape_bh *bh) -{ - idetape_init_pc(pc); - pc->c[0] = WRITE_6; - put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); - pc->c[1] = 1; - pc->idetape_callback = &idetape_rw_callback; - pc->flags |= PC_FLAG_WRITING; - pc->bh = bh; - pc->b_data = bh->b_data; - pc->b_count = atomic_read(&bh->b_count); - pc->buf = NULL; - pc->buf_size = length * tape->blk_size; - pc->req_xfer = pc->buf_size; - if (pc->req_xfer == tape->buffer_size) - pc->flags |= PC_FLAG_DMA_RECOMMENDED; + if (opcode == READ_6) { + pc->c[0] = READ_6; + atomic_set(&bh->b_count, 0); + } else if (opcode == WRITE_6) { + pc->c[0] = WRITE_6; + pc->flags |= PC_FLAG_WRITING; + pc->b_data = bh->b_data; + pc->b_count = atomic_read(&bh->b_count); + } } static ide_startstop_t idetape_do_request(ide_drive_t *drive, @@ -1211,8 +998,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } /* Retry a failed packet command */ - if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) - return idetape_issue_pc(drive, tape->failed_pc); + if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) { + pc = tape->failed_pc; + goto out; + } if (postponed_rq != NULL) if (rq != postponed_rq) { @@ -1262,14 +1051,16 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } if (rq->cmd[0] & REQ_IDETAPE_READ) { pc = idetape_next_pc_storage(drive); - idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, - (struct idetape_bh *)rq->special); + ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors, + (struct idetape_bh *)rq->special, + READ_6); goto out; } if (rq->cmd[0] & REQ_IDETAPE_WRITE) { pc = idetape_next_pc_storage(drive); - idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, - (struct idetape_bh *)rq->special); + ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors, + (struct idetape_bh *)rq->special, + WRITE_6); goto out; } if (rq->cmd[0] & REQ_IDETAPE_PC1) { @@ -1284,6 +1075,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } BUG(); out: + if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) + pc->flags |= PC_FLAG_DRQ_INTERRUPT; + return idetape_issue_pc(drive, pc); } @@ -1447,40 +1241,6 @@ static void idetape_init_merge_buffer(idetape_tape_t *tape) } } -static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - u8 *readpos = tape->pc->buf; - - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - if (!tape->pc->error) { - debug_log(DBG_SENSE, "BOP - %s\n", - (readpos[0] & 0x80) ? "Yes" : "No"); - debug_log(DBG_SENSE, "EOP - %s\n", - (readpos[0] & 0x40) ? "Yes" : "No"); - - if (readpos[0] & 0x4) { - printk(KERN_INFO "ide-tape: Block location is unknown" - "to the tape\n"); - clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); - idetape_end_request(drive, 0, 0); - } else { - debug_log(DBG_SENSE, "Block Location - %u\n", - be32_to_cpu(*(u32 *)&readpos[4])); - - tape->partition = readpos[1]; - tape->first_frame = - be32_to_cpu(*(u32 *)&readpos[4]); - set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); - idetape_end_request(drive, 1, 0); - } - } else { - idetape_end_request(drive, 0, 0); - } - return ide_stopped; -} - /* * Write a filemark if write_filemark=1. Flush the device buffers without * writing a filemark otherwise. @@ -1492,14 +1252,12 @@ static void idetape_create_write_filemark_cmd(ide_drive_t *drive, pc->c[0] = WRITE_FILEMARKS; pc->c[4] = write_filemark; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = TEST_UNIT_READY; - pc->idetape_callback = &idetape_pc_callback; } /* @@ -1518,12 +1276,16 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct ide_tape_obj *tape = drive->driver_data; - struct request rq; + struct request *rq; + int error; - idetape_init_rq(&rq, REQ_IDETAPE_PC1); - rq.buffer = (char *) pc; - rq.rq_disk = tape->disk; - return ide_do_drive_cmd(drive, &rq, ide_wait); + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd[0] = REQ_IDETAPE_PC1; + rq->buffer = (char *)pc; + error = blk_execute_rq(drive->queue, tape->disk, rq, 0); + blk_put_request(rq); + return error; } static void idetape_create_load_unload_cmd(ide_drive_t *drive, @@ -1533,7 +1295,6 @@ static void idetape_create_load_unload_cmd(ide_drive_t *drive, pc->c[0] = START_STOP; pc->c[4] = cmd; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) @@ -1585,7 +1346,6 @@ static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc) idetape_init_pc(pc); pc->c[0] = READ_POSITION; pc->req_xfer = 20; - pc->idetape_callback = &idetape_read_position_callback; } static int idetape_read_position(ide_drive_t *drive) @@ -1613,7 +1373,6 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } static int idetape_create_prevent_cmd(ide_drive_t *drive, @@ -1628,7 +1387,6 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_init_pc(pc); pc->c[0] = ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; - pc->idetape_callback = &idetape_pc_callback; return 1; } @@ -1700,26 +1458,33 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct idetape_bh *bh) { idetape_tape_t *tape = drive->driver_data; - struct request rq; + struct request *rq; + int ret, errors; debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd); - idetape_init_rq(&rq, cmd); - rq.rq_disk = tape->disk; - rq.special = (void *)bh; - rq.sector = tape->first_frame; - rq.nr_sectors = blocks; - rq.current_nr_sectors = blocks; - (void) ide_do_drive_cmd(drive, &rq, ide_wait); + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd[0] = cmd; + rq->rq_disk = tape->disk; + rq->special = (void *)bh; + rq->sector = tape->first_frame; + rq->nr_sectors = blocks; + rq->current_nr_sectors = blocks; + blk_execute_rq(drive->queue, tape->disk, rq, 0); + + errors = rq->errors; + ret = tape->blk_size * (blocks - rq->current_nr_sectors); + blk_put_request(rq); if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) return 0; if (tape->merge_bh) idetape_init_merge_buffer(tape); - if (rq.errors == IDETAPE_ERROR_GENERAL) + if (errors == IDETAPE_ERROR_GENERAL) return -EIO; - return (tape->blk_size * (blocks-rq.current_nr_sectors)); + return ret; } static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) @@ -1728,7 +1493,6 @@ static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) pc->c[0] = INQUIRY; pc->c[4] = 254; pc->req_xfer = 254; - pc->idetape_callback = &idetape_pc_callback; } static void idetape_create_rewind_cmd(ide_drive_t *drive, @@ -1737,7 +1501,6 @@ static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_init_pc(pc); pc->c[0] = REZERO_UNIT; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } static void idetape_create_erase_cmd(struct ide_atapi_pc *pc) @@ -1746,7 +1509,6 @@ static void idetape_create_erase_cmd(struct ide_atapi_pc *pc) pc->c[0] = ERASE; pc->c[1] = 1; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) @@ -1756,7 +1518,6 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]); pc->c[1] = cmd; pc->flags |= PC_FLAG_WAIT_FOR_DSC; - pc->idetape_callback = &idetape_pc_callback; } /* Queue up a character device originated write request. */ @@ -2751,9 +2512,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) * Ensure that the number we got makes sense; limit it within * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX. */ - tape->best_dsc_rw_freq = max_t(unsigned long, - min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), - IDETAPE_DSC_RW_MIN); + tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN, + IDETAPE_DSC_RW_MAX); printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, " "%lums tDSC%s\n", drive->name, tape->name, *(u16 *)&tape->caps[14], @@ -2905,11 +2665,6 @@ static int ide_tape_probe(ide_drive_t *drive) " the driver\n", drive->name); goto failed; } - if (drive->scsi) { - printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi" - " emulation.\n", drive->name); - goto failed; - } tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL); if (tape == NULL) { printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n", |