Messages in this thread Patches in this message | | | Date | Mon, 9 Dec 2002 15:03:39 -0500 (EST) | From | Alan Stern <> | Subject | Patch for ide-tape driver |
| |
Alan, Marcelo, and all:
As suggested earlier by Alan Cox, now that 2.4.20 has been released I am resubmitting my patches for the ide-tape driver. It fixes a few nasty bugs and makes some other small improvements in the original. It has been tested by Willem Riede, who maintains the OnStream tape driver.
Attached are patch files for both 2.4.20 and 2.5.50. Please apply them when you have a chance.
Thank you,
Alan Stern --- linux/drivers/ide/ide-tape.c.orig Wed Oct 16 11:47:36 2002 +++ linux/drivers/ide/ide-tape.c Thu Oct 17 15:12:28 2002 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001 + * linux/drivers/ide/ide-tape.c Version 1.17b Oct, 2002 * * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il> * @@ -291,6 +291,28 @@ * Ver 1.17a Apr 2001 Willem Riede osst@riede.org * - Get drive's actual block size from mode sense block descriptor * - Limit size of pipeline + * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu> + * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used + * it in the code! + * Actually removed aborted stages in idetape_abort_pipeline + * instead of just changing the command code. + * Made the transfer byte count for Request Sense equal to the + * actual length of the data transfer. + * Changed handling of partial data transfers: they do not + * cause DMA errors. + * Moved initiation of DMA transfers to the correct place. + * Removed reference to unallocated memory. + * Made __idetape_discard_read_pipeline return the number of + * sectors skipped, not the number of stages. + * Replaced errant kfree() calls with __idetape_kfree_stage(). + * Fixed off-by-one error in testing the pipeline length. + * Fixed handling of filemarks in the read pipeline. + * Small code optimization for MTBSF and MTBSFM ioctls. + * Don't try to unlock the door during device close if is + * already unlocked! + * Cosmetic fixes to miscellaneous debugging output messages. + * Set the minimum /proc/ide/hd?/settings values for "pipeline", + * "pipeline_min", and "pipeline_max" to 1. * * Here are some words from the first releases of hd.c, which are quoted * in ide.c and apply here as well: @@ -400,7 +422,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ -#define IDETAPE_VERSION "1.17a" +#define IDETAPE_VERSION "1.17b" #include <linux/config.h> #include <linux/module.h> @@ -577,9 +599,10 @@ * whenever we sense that the pipeline is empty, until we reach * the optimum value or until we reach MAX. * - * Setting the following parameter to 0 will disable the pipelined mode. + * Setting the following parameter to 0 is illegal: the pipelined mode + * cannot be disabled (calculate_speeds() divides by tape->max_stages.) */ -#define IDETAPE_MIN_PIPELINE_STAGES 200 +#define IDETAPE_MIN_PIPELINE_STAGES 1 #define IDETAPE_MAX_PIPELINE_STAGES 400 #define IDETAPE_INCREASE_STAGES_RATE 20 @@ -601,8 +624,8 @@ * is verified to be stable enough. This will make it much more * esthetic. */ -#define IDETAPE_DEBUG_INFO 1 -#define IDETAPE_DEBUG_LOG 1 +#define IDETAPE_DEBUG_INFO 0 +#define IDETAPE_DEBUG_LOG 0 #define IDETAPE_DEBUG_LOG_VERBOSE 0 #define IDETAPE_DEBUG_BUGS 1 @@ -1696,24 +1719,6 @@ } } -static void idetape_abort_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); -#endif - while (stage) { - if (stage->rq.cmd == IDETAPE_WRITE_RQ) - stage->rq.cmd = IDETAPE_ABORTED_WRITE_RQ; - else if (stage->rq.cmd == IDETAPE_READ_RQ) - stage->rq.cmd = IDETAPE_ABORTED_READ_RQ; - stage = stage->next; - } -} - /* * idetape_active_next_stage will declare the next stage as "active". */ @@ -1758,7 +1763,7 @@ printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n"); #endif /* IDETAPE_DEBUG_LOG */ - tape->max_stages += increase; + tape->max_stages += IDE_MAX(increase, 1); tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline); tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline); } @@ -1831,6 +1836,29 @@ } } +static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_stage_t *stage = tape->next_stage; + idetape_stage_t *nstage; + +#if IDETAPE_DEBUG_LOG + if (tape->debug_level >= 4) + printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); +#endif + while (stage) { + nstage = stage->next; + idetape_kfree_stage(tape, stage); + --tape->nr_stages; + --tape->nr_pending_stages; + stage = nstage; + } + tape->last_stage = last_stage; + if (last_stage) + last_stage->next = NULL; + tape->next_stage = NULL; +} + /* * idetape_end_request is used to finish servicing a request, and to * insert a pending pipeline request into the main device queue. @@ -1843,6 +1871,7 @@ unsigned long flags; int error; int remove_stage = 0; + idetape_stage_t *active_stage; #if ONSTREAM_DEBUG idetape_stage_t *stage; os_aux_t *aux; @@ -1865,6 +1894,7 @@ spin_lock_irqsave(&tape->spinlock, flags); if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ + active_stage = tape->active_stage; tape->active_stage = NULL; tape->active_data_request = NULL; tape->nr_pending_stages--; @@ -1887,15 +1917,17 @@ printk("ide-tape: %s: skipping over config parition..\n", tape->name); #endif tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } remove_stage = 1; if (error) { set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline (drive); + idetape_abort_pipeline(drive, active_stage); if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); @@ -1904,14 +1936,16 @@ tape->nr_pending_stages++; tape->next_stage = tape->first_stage; rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } } else if (rq->cmd == IDETAPE_READ_RQ) { if (error == IDETAPE_ERROR_EOD) { set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - idetape_abort_pipeline(drive); + idetape_abort_pipeline(drive, active_stage); } } if (tape->next_stage != NULL && !tape->onstream_write_error) { @@ -1957,7 +1991,7 @@ idetape_init_pc (pc); pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; pc->c[4] = 20; - pc->request_transfer = 18; + pc->request_transfer = 20; pc->callback = &idetape_request_sense_callback; } @@ -2057,7 +2091,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->dmaproc(ide_dma_end, drive)) { + if (HWIF(drive)->dmaproc(ide_dma_end, drive) || status.b.check) { /* * A DMA error is sometimes expected. For example, * if the tape is crossing a filemark during a @@ -2069,8 +2103,18 @@ * 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) + */ set_bit (PC_DMA_ERROR, &pc->flags); - } else if (!status.b.check) { + } else { pc->actually_transferred = pc->request_transfer; idetape_update_buffers (pc); } @@ -2103,7 +2147,7 @@ if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name); + printk(KERN_INFO "ide-tape: %s: I/O error\n",tape->name); #endif /* IDETAPE_DEBUG_LOG */ if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { printk (KERN_ERR "ide-tape: I/O error in request sense command\n"); @@ -2255,6 +2299,10 @@ } tape->cmd_start_time = jiffies; ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ +#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) /* Begin DMA, if necessary */ + (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); +#endif atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ return ide_started; } @@ -2279,8 +2327,7 @@ /* * We will "abort" retrying a packet command in case * a legitimate error code was received (crossing a - * filemark, or DMA error in the end of media, for - * example). + * filemark, or end of the media, for example). */ if (!test_bit (PC_ABORT, &pc->flags)) { if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && tape->sense_key == 2 && @@ -2297,7 +2344,7 @@ } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Retry number - %d\n", pc->retries); + printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]); #endif /* IDETAPE_DEBUG_LOG */ pc->retries++; @@ -2321,9 +2368,8 @@ OUT_BYTE (bcount.b.low, IDE_BCOUNTL_REG); OUT_BYTE (drive->select.all, IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ + if (dma_ok) { /* Will begin DMA later */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { @@ -3086,7 +3132,7 @@ tape->waiting = &wait; spin_unlock(&tape->spinlock); wait_for_completion(&wait); - rq->waiting = NULL; + /* The stage and its struct request have been deallocated */ tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } @@ -3345,11 +3391,15 @@ if (tape->chrdev_direction != idetape_direction_read) return 0; + cnt = tape->merge_stage_size / tape->tape_block_size; + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++cnt; /* Filemarks count as 1 sector */ tape->merge_stage_size = 0; if (tape->merge_stage != NULL) { __idetape_kfree_stage (tape->merge_stage); tape->merge_stage = NULL; } + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); tape->chrdev_direction = idetape_direction_none; if (tape->first_stage == NULL) @@ -3361,9 +3411,14 @@ idetape_wait_for_request(drive, tape->active_data_request); spin_unlock_irqrestore(&tape->spinlock, flags); - cnt = tape->nr_stages - tape->nr_pending_stages; - while (tape->first_stage != NULL) - idetape_remove_stage_head (drive); + while (tape->first_stage != NULL) { + struct request *rq_ptr = &tape->first_stage->rq; + + cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors; + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + ++cnt; + idetape_remove_stage_head(drive); + } tape->nr_pending_stages = 0; tape->max_stages = tape->min_pipeline; return cnt; @@ -3951,7 +4006,7 @@ */ bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh); if (bytes_read < 0) { - kfree (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return bytes_read; @@ -3963,7 +4018,7 @@ rq.cmd = IDETAPE_READ_RQ; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; - if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) { + if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages < max_stages) { new_stage = idetape_kmalloc_stage (tape); while (new_stage != NULL) { new_stage->rq = rq; @@ -4073,6 +4128,12 @@ #endif /* IDETAPE_DEBUG_LOG */ /* + * If we are at a filemark, return a read length of 0 + */ + if (test_bit(IDETAPE_FILEMARK, &tape->flags)) + return 0; + + /* * Wait for the next logical block to be available at the head * of the pipeline */ @@ -4099,14 +4160,7 @@ } if (rq_ptr->errors == IDETAPE_ERROR_EOD) return 0; - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) { - idetape_switch_buffers (tape, tape->first_stage); - set_bit (IDETAPE_FILEMARK, &tape->flags); -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - } else { + else { idetape_switch_buffers (tape, tape->first_stage); if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { #if ONSTREAM_DEBUG @@ -4114,7 +4168,8 @@ printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); #endif } - clear_bit (IDETAPE_FILEMARK, &tape->flags); + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + set_bit(IDETAPE_FILEMARK, &tape->flags); spin_lock_irqsave(&tape->spinlock, flags); idetape_remove_stage_head (drive); spin_unlock_irqrestore(&tape->spinlock, flags); @@ -4478,6 +4533,14 @@ tape->restart_speed_control_req = 1; return retval; } + + if (mt_count == 0) + return 0; + if (MTBSF == mt_op || MTBSFM == mt_op) { + if (!tape->capabilities.sprev) + return -EIO; + mt_count = - mt_count; + } if (tape->chrdev_direction == idetape_direction_read) { /* @@ -4485,28 +4548,36 @@ * filemarks. */ tape->merge_stage_size = 0; - clear_bit (IDETAPE_FILEMARK, &tape->flags); + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++count; while (tape->first_stage != NULL) { - idetape_wait_first_stage(drive); - if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) - count++; if (count == mt_count) { - switch (mt_op) { - case MTFSF: - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - case MTFSFM: - return (0); - default: - break; - } + if (mt_op == MTFSFM) + set_bit(IDETAPE_FILEMARK, &tape->flags); + return 0; } spin_lock_irqsave(&tape->spinlock, flags); + if (tape->first_stage == tape->active_stage) { + /* + * We have reached the active stage in the read pipeline. + * There is no point in allowing the drive to continue + * reading any farther, so we stop the pipeline. + * + * This section should be moved to a separate subroutine, + * because a similar function is performed in + * __idetape_discard_read_pipeline(), for example. + */ + tape->next_stage = NULL; + spin_unlock_irqrestore(&tape->spinlock, flags); + idetape_wait_first_stage(drive); + tape->next_stage = tape->first_stage->next; + } else + spin_unlock_irqrestore(&tape->spinlock, flags); + if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) + ++count; idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); } - idetape_discard_read_pipeline (drive, 1); + idetape_discard_read_pipeline(drive, 0); } /* @@ -4515,25 +4586,17 @@ */ switch (mt_op) { case MTFSF: + case MTBSF: idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); return (idetape_queue_pc_tail (drive, &pc)); case MTFSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTFSF, mt_count-count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTBSF, 1)); - case MTBSF: - if (!tape->capabilities.sprev) - return (-EIO); - idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive, &pc)); case MTBSFM: if (!tape->capabilities.sprev) return (-EIO); - retval = idetape_space_over_filemarks (drive, MTBSF, mt_count+count); + retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count); if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTFSF, 1)); + count = (MTBSFM == mt_op ? 1 : -1); + return (idetape_space_over_filemarks(drive, MTFSF, count)); default: printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); return (-EIO); @@ -4862,7 +4925,7 @@ */ retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh); if (retval < 0) { - kfree (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return retval; @@ -5436,9 +5499,11 @@ MOD_DEC_USE_COUNT; return -EBUSY; } - idetape_read_position(drive); + if (tape->onstream) + idetape_read_position(drive); MOD_DEC_USE_COUNT; - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); + if (tape->chrdev_direction != idetape_direction_read) + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (tape->chrdev_direction == idetape_direction_none) { MOD_INC_USE_COUNT; @@ -5511,10 +5576,11 @@ if (minor < 128) (void) idetape_rewind_tape (drive); if (tape->chrdev_direction == idetape_direction_none) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) + if (tape->door_locked == DOOR_LOCKED) { + if (idetape_create_prevent_cmd(drive, &pc, 0)) { if (!idetape_queue_pc_tail (drive, &pc)) tape->door_locked = DOOR_UNLOCKED; + } } MOD_DEC_USE_COUNT; } @@ -5548,34 +5614,34 @@ printk (KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); printk (KERN_INFO "ide-tape: Protocol Type: "); switch (gcw.protocol) { - case 0: case 1: printk (KERN_INFO "ATA\n");break; - case 2: printk (KERN_INFO "ATAPI\n");break; - case 3: printk (KERN_INFO "Reserved (Unknown to ide-tape)\n");break; + case 0: case 1: printk ("ATA\n");break; + case 2: printk ("ATAPI\n");break; + case 3: printk ("Reserved (Unknown to ide-tape)\n");break; } printk (KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); switch (gcw.device_type) { - case 0: printk (KERN_INFO "Direct-access Device\n");break; - case 1: printk (KERN_INFO "Streaming Tape Device\n");break; - case 2: case 3: case 4: printk (KERN_INFO "Reserved\n");break; - case 5: printk (KERN_INFO "CD-ROM Device\n");break; - case 6: printk (KERN_INFO "Reserved\n"); - case 7: printk (KERN_INFO "Optical memory Device\n");break; - case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break; - default: printk (KERN_INFO "Reserved\n"); + case 0: printk ("Direct-access Device\n");break; + case 1: printk ("Streaming Tape Device\n");break; + case 2: case 3: case 4: printk ("Reserved\n");break; + case 5: printk ("CD-ROM Device\n");break; + case 6: printk ("Reserved\n"); + case 7: printk ("Optical memory Device\n");break; + case 0x1f: printk ("Unknown or no Device type\n");break; + default: printk ("Reserved\n"); } printk (KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); printk (KERN_INFO "ide-tape: Command Packet DRQ Type: "); switch (gcw.drq_type) { - case 0: printk (KERN_INFO "Microprocessor DRQ\n");break; - case 1: printk (KERN_INFO "Interrupt DRQ\n");break; - case 2: printk (KERN_INFO "Accelerated DRQ\n");break; - case 3: printk (KERN_INFO "Reserved\n");break; + case 0: printk ("Microprocessor DRQ\n");break; + case 1: printk ("Interrupt DRQ\n");break; + case 2: printk ("Accelerated DRQ\n");break; + case 3: printk ("Reserved\n");break; } printk (KERN_INFO "ide-tape: Command Packet Size: "); switch (gcw.packet_size) { - case 0: printk (KERN_INFO "12 bytes\n");break; - case 1: printk (KERN_INFO "16 bytes\n");break; - default: printk (KERN_INFO "Reserved\n");break; + case 0: printk ("12 bytes\n");break; + case 1: printk ("16 bytes\n");break; + default: printk ("Reserved\n");break; } printk (KERN_INFO "ide-tape: Model: %.40s\n",id->model); printk (KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); @@ -5591,44 +5657,44 @@ printk (KERN_INFO "ide-tape: Single Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_1word & mask) - printk (KERN_INFO "%d ",i); + printk ("%d ",i); if (id->dma_1word & (mask << 8)) - printk (KERN_INFO "(active) "); + printk ("(active) "); } - printk (KERN_INFO "\n"); + printk ("\n"); printk (KERN_INFO "ide-tape: Multi Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_mword & mask) - printk (KERN_INFO "%d ",i); + printk ("%d ",i); if (id->dma_mword & (mask << 8)) - printk (KERN_INFO "(active) "); + printk ("(active) "); } - printk (KERN_INFO "\n"); + printk ("\n"); if (id->field_valid & 0x0002) { printk (KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); printk (KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); if (id->eide_dma_min == 0) - printk (KERN_INFO "Not supported\n"); + printk ("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_dma_min); + printk ("%d ns\n",id->eide_dma_min); printk (KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); if (id->eide_dma_time == 0) - printk (KERN_INFO "Not supported\n"); + printk ("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_dma_time); + printk ("%d ns\n",id->eide_dma_time); printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); if (id->eide_pio == 0) - printk (KERN_INFO "Not supported\n"); + printk ("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_pio); + printk ("%d ns\n",id->eide_pio); printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); if (id->eide_pio_iordy == 0) - printk (KERN_INFO "Not supported\n"); + printk ("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_pio_iordy); + printk ("%d ns\n",id->eide_pio_iordy); } else printk (KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); @@ -5937,9 +6003,9 @@ * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); @@ -6054,8 +6120,11 @@ si_meminfo(&si); if ( tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size); - tape->min_pipeline = tape->max_stages; - tape->max_pipeline = tape->max_stages * 2; + tape->max_stages = IDE_MIN(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES); + tape->min_pipeline = IDE_MIN(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES); + tape->max_pipeline = IDE_MIN(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES); + if (tape->max_stages == 0) + tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1; t1 = (tape->stage_size * HZ) / (speed * 1000); tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);--- linux/drivers/ide/ide-tape.c.orig Mon Dec 9 14:42:07 2002 +++ linux/drivers/ide/ide-tape.c Mon Dec 9 14:46:04 2002 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001 + * linux/drivers/ide/ide-tape.c Version 1.17b Oct, 2002 * * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il> * @@ -291,6 +291,28 @@ * Ver 1.17a Apr 2001 Willem Riede osst@riede.org * - Get drive's actual block size from mode sense block descriptor * - Limit size of pipeline + * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu> + * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used + * it in the code! + * Actually removed aborted stages in idetape_abort_pipeline + * instead of just changing the command code. + * Made the transfer byte count for Request Sense equal to the + * actual length of the data transfer. + * Changed handling of partial data transfers: they do not + * cause DMA errors. + * Moved initiation of DMA transfers to the correct place. + * Removed reference to unallocated memory. + * Made __idetape_discard_read_pipeline return the number of + * sectors skipped, not the number of stages. + * Replaced errant kfree() calls with __idetape_kfree_stage(). + * Fixed off-by-one error in testing the pipeline length. + * Fixed handling of filemarks in the read pipeline. + * Small code optimization for MTBSF and MTBSFM ioctls. + * Don't try to unlock the door during device close if is + * already unlocked! + * Cosmetic fixes to miscellaneous debugging output messages. + * Set the minimum /proc/ide/hd?/settings values for "pipeline", + * "pipeline_min", and "pipeline_max" to 1. * * Here are some words from the first releases of hd.c, which are quoted * in ide.c and apply here as well: @@ -400,7 +422,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ -#define IDETAPE_VERSION "1.17a" +#define IDETAPE_VERSION "1.17b" #include <linux/config.h> #include <linux/module.h> @@ -577,9 +599,10 @@ * whenever we sense that the pipeline is empty, until we reach * the optimum value or until we reach MAX. * - * Setting the following parameter to 0 will disable the pipelined mode. + * Setting the following parameter to 0 is illegal: the pipelined mode + * cannot be disabled (calculate_speeds() divides by tape->max_stages.) */ -#define IDETAPE_MIN_PIPELINE_STAGES 200 +#define IDETAPE_MIN_PIPELINE_STAGES 1 #define IDETAPE_MAX_PIPELINE_STAGES 400 #define IDETAPE_INCREASE_STAGES_RATE 20 @@ -601,8 +624,8 @@ * is verified to be stable enough. This will make it much more * esthetic. */ -#define IDETAPE_DEBUG_INFO 1 -#define IDETAPE_DEBUG_LOG 1 +#define IDETAPE_DEBUG_INFO 0 +#define IDETAPE_DEBUG_LOG 0 #define IDETAPE_DEBUG_LOG_VERBOSE 0 #define IDETAPE_DEBUG_BUGS 1 @@ -1610,24 +1633,6 @@ } } -static void idetape_abort_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); -#endif - while (stage) { - if (stage->rq.flags == IDETAPE_WRITE_RQ) - stage->rq.flags = IDETAPE_ABORTED_WRITE_RQ; - else if (stage->rq.flags == IDETAPE_READ_RQ) - stage->rq.flags = IDETAPE_ABORTED_READ_RQ; - stage = stage->next; - } -} - /* * idetape_active_next_stage will declare the next stage as "active". */ @@ -1672,7 +1677,7 @@ printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n"); #endif /* IDETAPE_DEBUG_LOG */ - tape->max_stages += increase; + tape->max_stages += max(increase, 1); tape->max_stages = max(tape->max_stages, tape->min_pipeline); tape->max_stages = min(tape->max_stages, tape->max_pipeline); } @@ -1745,6 +1750,29 @@ } } +static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_stage_t *stage = tape->next_stage; + idetape_stage_t *nstage; + +#if IDETAPE_DEBUG_LOG + if (tape->debug_level >= 4) + printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); +#endif + while (stage) { + nstage = stage->next; + idetape_kfree_stage(tape, stage); + --tape->nr_stages; + --tape->nr_pending_stages; + stage = nstage; + } + tape->last_stage = last_stage; + if (last_stage) + last_stage->next = NULL; + tape->next_stage = NULL; +} + /* * idetape_end_request is used to finish servicing a request, and to * insert a pending pipeline request into the main device queue. @@ -1756,6 +1784,7 @@ unsigned long flags; int error; int remove_stage = 0; + idetape_stage_t *active_stage; #if ONSTREAM_DEBUG idetape_stage_t *stage; os_aux_t *aux; @@ -1780,6 +1809,7 @@ /* The request was a pipelined data transfer request */ if (tape->active_data_request == rq) { + active_stage = tape->active_stage; tape->active_stage = NULL; tape->active_data_request = NULL; tape->nr_pending_stages--; @@ -1802,15 +1832,17 @@ printk("ide-tape: %s: skipping over config parition..\n", tape->name); #endif tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } remove_stage = 1; if (error) { set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline(drive); + idetape_abort_pipeline(drive, active_stage); if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { @@ -1821,14 +1853,16 @@ tape->nr_pending_stages++; tape->next_stage = tape->first_stage; rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } } else if (rq->flags == IDETAPE_READ_RQ) { if (error == IDETAPE_ERROR_EOD) { set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - idetape_abort_pipeline(drive); + idetape_abort_pipeline(drive, active_stage); } } if (tape->next_stage != NULL && !tape->onstream_write_error) { @@ -1879,7 +1913,7 @@ idetape_init_pc(pc); pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; pc->c[4] = 20; - pc->request_transfer = 18; + pc->request_transfer = 20; pc->callback = &idetape_request_sense_callback; } @@ -1980,7 +2014,7 @@ status.all = HWIF(drive)->INB(IDE_STATUS_REG); if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->ide_dma_end(drive)) { + if (HWIF(drive)->ide_dma_end(drive) || status.b.check) { /* * A DMA error is sometimes expected. For example, * if the tape is crossing a filemark during a @@ -1992,8 +2026,18 @@ * 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) + */ set_bit(PC_DMA_ERROR, &pc->flags); - } else if (!status.b.check) { + } else { pc->actually_transferred = pc->request_transfer; idetape_update_buffers(pc); } @@ -2029,7 +2073,7 @@ if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: I/O error, ", + printk(KERN_INFO "ide-tape: %s: I/O error\n", tape->name); #endif /* IDETAPE_DEBUG_LOG */ if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { @@ -2195,6 +2239,10 @@ BUG(); /* Set the interrupt routine */ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); +#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) /* Begin DMA, if necessary */ + (void) (HWIF(drive)->ide_dma_begin(drive)); +#endif /* Send the actual packet */ HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); return ide_started; @@ -2223,8 +2271,7 @@ /* * We will "abort" retrying a packet command in case * a legitimate error code was received (crossing a - * filemark, or DMA error in the end of media, for - * example). + * filemark, or end of the media, for example). */ if (!test_bit(PC_ABORT, &pc->flags)) { if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && @@ -2249,7 +2296,7 @@ } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: Retry number - %d\n", pc->retries); + printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]); #endif /* IDETAPE_DEBUG_LOG */ pc->retries++; @@ -2275,9 +2322,8 @@ OUT_BYTE(bcount.b.high, IDE_BCOUNTH_REG); OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG); OUT_BYTE(drive->select.all, IDE_SELECT_REG); - if (dma_ok) { /* Begin DMA, if necessary */ + if (dma_ok) { /* Will begin DMA later */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); } if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { if (HWGROUP(drive)->handler != NULL) /* paranoia check */ @@ -3069,7 +3115,7 @@ tape->waiting = &wait; spin_unlock(&tape->spinlock); wait_for_completion(&wait); - rq->waiting = NULL; + /* The stage and its struct request have been deallocated */ tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } @@ -3333,11 +3379,15 @@ if (tape->chrdev_direction != idetape_direction_read) return 0; + cnt = tape->merge_stage_size / tape->tape_block_size; + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++cnt; /* Filemarks count as 1 sector */ tape->merge_stage_size = 0; if (tape->merge_stage != NULL) { __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; } + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); tape->chrdev_direction = idetape_direction_none; if (tape->first_stage == NULL) @@ -3349,9 +3399,14 @@ idetape_wait_for_request(drive, tape->active_data_request); spin_unlock_irqrestore(&tape->spinlock, flags); - cnt = tape->nr_stages - tape->nr_pending_stages; - while (tape->first_stage != NULL) + while (tape->first_stage != NULL) { + struct request *rq_ptr = &tape->first_stage->rq; + + cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors; + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + ++cnt; idetape_remove_stage_head(drive); + } tape->nr_pending_stages = 0; tape->max_stages = tape->min_pipeline; return cnt; @@ -3946,7 +4001,7 @@ */ bytes_read = idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bio); if (bytes_read < 0) { - kfree(tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return bytes_read; @@ -3959,7 +4014,7 @@ rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && - tape->nr_stages <= max_stages) { + tape->nr_stages < max_stages) { new_stage = idetape_kmalloc_stage(tape); while (new_stage != NULL) { new_stage->rq = rq; @@ -4069,6 +4124,12 @@ #endif /* IDETAPE_DEBUG_LOG */ /* + * If we are at a filemark, return a read length of 0 + */ + if (test_bit(IDETAPE_FILEMARK, &tape->flags)) + return 0; + + /* * Wait for the next logical block to be available at the head * of the pipeline */ @@ -4097,14 +4158,7 @@ } if (rq_ptr->errors == IDETAPE_ERROR_EOD) return 0; - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) { - idetape_switch_buffers(tape, tape->first_stage); - set_bit(IDETAPE_FILEMARK, &tape->flags); -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - } else { + else { idetape_switch_buffers(tape, tape->first_stage); if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { #if ONSTREAM_DEBUG @@ -4112,7 +4166,8 @@ printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); #endif } - clear_bit(IDETAPE_FILEMARK, &tape->flags); + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + set_bit(IDETAPE_FILEMARK, &tape->flags); spin_lock_irqsave(&tape->spinlock, flags); idetape_remove_stage_head(drive); spin_unlock_irqrestore(&tape->spinlock, flags); @@ -4455,6 +4510,14 @@ tape->restart_speed_control_req = 1; return retval; } + + if (mt_count == 0) + return 0; + if (MTBSF == mt_op || MTBSFM == mt_op) { + if (!tape->capabilities.sprev) + return -EIO; + mt_count = - mt_count; + } if (tape->chrdev_direction == idetape_direction_read) { /* @@ -4462,28 +4525,36 @@ * filemarks. */ tape->merge_stage_size = 0; - clear_bit(IDETAPE_FILEMARK, &tape->flags); + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++count; while (tape->first_stage != NULL) { - idetape_wait_first_stage(drive); - if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) - count++; if (count == mt_count) { - switch (mt_op) { - case MTFSF: - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - case MTFSFM: - return (0); - default: - break; - } + if (mt_op == MTFSFM) + set_bit(IDETAPE_FILEMARK, &tape->flags); + return 0; } spin_lock_irqsave(&tape->spinlock, flags); + if (tape->first_stage == tape->active_stage) { + /* + * We have reached the active stage in the read pipeline. + * There is no point in allowing the drive to continue + * reading any farther, so we stop the pipeline. + * + * This section should be moved to a separate subroutine, + * because a similar function is performed in + * __idetape_discard_read_pipeline(), for example. + */ + tape->next_stage = NULL; + spin_unlock_irqrestore(&tape->spinlock, flags); + idetape_wait_first_stage(drive); + tape->next_stage = tape->first_stage->next; + } else + spin_unlock_irqrestore(&tape->spinlock, flags); + if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) + ++count; idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); } - idetape_discard_read_pipeline(drive, 1); + idetape_discard_read_pipeline(drive, 0); } /* @@ -4492,25 +4563,17 @@ */ switch (mt_op) { case MTFSF: + case MTBSF: idetape_create_space_cmd(&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); return (idetape_queue_pc_tail(drive, &pc)); case MTFSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count); - if (retval) return (retval); - return (idetape_space_over_filemarks(drive, MTBSF, 1)); - case MTBSF: - if (!tape->capabilities.sprev) - return (-EIO); - idetape_create_space_cmd(&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail(drive, &pc)); case MTBSFM: if (!tape->capabilities.sprev) return (-EIO); - retval = idetape_space_over_filemarks(drive, MTBSF, mt_count+count); + retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count); if (retval) return (retval); - return (idetape_space_over_filemarks(drive, MTFSF, 1)); + count = (MTBSFM == mt_op ? 1 : -1); + return (idetape_space_over_filemarks(drive, MTFSF, count)); default: printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); return (-EIO); @@ -4861,7 +4924,7 @@ */ retval = idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bio); if (retval < 0) { - kfree(tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return retval; @@ -5447,8 +5510,10 @@ printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); return -EBUSY; } - idetape_read_position(drive); - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); + if (tape->onstream) + idetape_read_position(drive); + if (tape->chrdev_direction != idetape_direction_read) + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (tape->chrdev_direction == idetape_direction_none) { if (idetape_create_prevent_cmd(drive, &pc, 1)) { @@ -5520,10 +5585,11 @@ if (minor < 128) (void) idetape_rewind_tape(drive); if (tape->chrdev_direction == idetape_direction_none) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) + if (tape->door_locked == DOOR_LOCKED) { + if (idetape_create_prevent_cmd(drive, &pc, 0)) { if (!idetape_queue_pc_tail(drive, &pc)) tape->door_locked = DOOR_UNLOCKED; + } } } clear_bit(IDETAPE_BUSY, &tape->flags); @@ -5556,34 +5622,34 @@ printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); printk(KERN_INFO "ide-tape: Protocol Type: "); switch (gcw.protocol) { - case 0: case 1: printk(KERN_INFO "ATA\n");break; - case 2: printk(KERN_INFO "ATAPI\n");break; - case 3: printk(KERN_INFO "Reserved (Unknown to ide-tape)\n");break; + case 0: case 1: printk("ATA\n");break; + case 2: printk("ATAPI\n");break; + case 3: printk("Reserved (Unknown to ide-tape)\n");break; } printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); switch (gcw.device_type) { - case 0: printk(KERN_INFO "Direct-access Device\n");break; - case 1: printk(KERN_INFO "Streaming Tape Device\n");break; - case 2: case 3: case 4: printk(KERN_INFO "Reserved\n");break; - case 5: printk(KERN_INFO "CD-ROM Device\n");break; - case 6: printk(KERN_INFO "Reserved\n"); - case 7: printk(KERN_INFO "Optical memory Device\n");break; - case 0x1f: printk(KERN_INFO "Unknown or no Device type\n");break; - default: printk(KERN_INFO "Reserved\n"); + case 0: printk("Direct-access Device\n");break; + case 1: printk("Streaming Tape Device\n");break; + case 2: case 3: case 4: printk("Reserved\n");break; + case 5: printk("CD-ROM Device\n");break; + case 6: printk("Reserved\n"); + case 7: printk("Optical memory Device\n");break; + case 0x1f: printk("Unknown or no Device type\n");break; + default: printk("Reserved\n"); } printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); printk(KERN_INFO "ide-tape: Command Packet DRQ Type: "); switch (gcw.drq_type) { - case 0: printk(KERN_INFO "Microprocessor DRQ\n");break; - case 1: printk(KERN_INFO "Interrupt DRQ\n");break; - case 2: printk(KERN_INFO "Accelerated DRQ\n");break; - case 3: printk(KERN_INFO "Reserved\n");break; + case 0: printk("Microprocessor DRQ\n");break; + case 1: printk("Interrupt DRQ\n");break; + case 2: printk("Accelerated DRQ\n");break; + case 3: printk("Reserved\n");break; } printk(KERN_INFO "ide-tape: Command Packet Size: "); switch (gcw.packet_size) { - case 0: printk(KERN_INFO "12 bytes\n");break; - case 1: printk(KERN_INFO "16 bytes\n");break; - default: printk(KERN_INFO "Reserved\n");break; + case 0: printk("12 bytes\n");break; + case 1: printk("16 bytes\n");break; + default: printk("Reserved\n");break; } printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model); printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); @@ -5599,45 +5665,45 @@ printk(KERN_INFO "ide-tape: Single Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_1word & mask) - printk(KERN_INFO "%d ",i); + printk("%d ",i); if (id->dma_1word & (mask << 8)) - printk(KERN_INFO "(active) "); + printk("(active) "); } - printk(KERN_INFO "\n"); + printk("\n"); printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_mword & mask) - printk(KERN_INFO "%d ",i); + printk("%d ",i); if (id->dma_mword & (mask << 8)) - printk(KERN_INFO "(active) "); + printk("(active) "); } - printk(KERN_INFO "\n"); + printk("\n"); if (id->field_valid & 0x0002) { printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n", id->eide_pio_modes & 1 ? "Mode 3":"None"); printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); if (id->eide_dma_min == 0) - printk(KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk(KERN_INFO "%d ns\n",id->eide_dma_min); + printk("%d ns\n",id->eide_dma_min); printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); if (id->eide_dma_time == 0) - printk(KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk(KERN_INFO "%d ns\n",id->eide_dma_time); + printk("%d ns\n",id->eide_dma_time); printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); if (id->eide_pio == 0) - printk(KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk(KERN_INFO "%d ns\n",id->eide_pio); + printk("%d ns\n",id->eide_pio); printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); if (id->eide_pio_iordy == 0) - printk(KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk(KERN_INFO "%d ns\n",id->eide_pio_iordy); + printk("%d ns\n",id->eide_pio_iordy); } else printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); @@ -5946,9 +6012,9 @@ * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); @@ -6063,8 +6129,11 @@ si_meminfo(&si); if (tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size); - tape->min_pipeline = tape->max_stages; - tape->max_pipeline = tape->max_stages * 2; + tape->max_stages = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES); + tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES); + tape->max_pipeline = min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES); + if (tape->max_stages == 0) + tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1; t1 = (tape->stage_size * HZ) / (speed * 1000); tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125); | |